1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17#include <stdio.h>
18#include <string.h>
19#include <unistd.h>
20#include <signal.h>
21#include <sys/types.h>
22#include <sys/time.h>
23#include <sys/wait.h>
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#include <errno.h>
28#include <linux/lp.h>
29#include <fcntl.h>
30#include "wlancom.h"
31#include "lp_asus.h"
32#include "syslog.h"
33
34#include <bcmnvram.h>
35#include <netinet/tcp.h>
36
37/*Lisa*/
38#include	<stdlib.h>
39#include	<getopt.h>
40#include	<ctype.h>
41#include	<fcntl.h>
42#include	<netdb.h>
43#include	<syslog.h>
44#include	<sys/resource.h>
45#include	<sys/stat.h>
46#include 	<sys/ioctl.h>
47#define		BASEPORT	9100
48#ifdef 		DEBUG
49#define		PRINT(...)
50#else
51#define		PRINT	printf
52#endif
53#define 	Raw_Printing_with_ASUS
54#define 	LOGOPTS		(LOG_PERROR|LOG_PID|LOG_LPR|LOG_ERR)
55
56/* 2004/09/10, added by Joey
57 * The printer server desing
58 * Remote Port/LPR/Raw
59 * 1. fork() for one printing job at the same time.
60 * 2. the nack is processed in parent process.
61 * 3. busyflag is used globally in parent proces
62 * 4. lptstatus.busy is used between parent and child
63 */
64
65//JY
66#include "lp.h"
67//#define MAX(a, b) ((a) > (b) ? (a) : (b))//JY1112
68
69
70extern int          errno;
71
72
73#ifdef LPR_with_ASUS//JY1112
74#define PNT_SVR_PORT_ASUS    3838
75#endif
76#define PNT_SVR_PORT_LPR 515
77#define PRINT printf
78
79#define UCHAR unsigned char
80
81#define STATUS_FILE "/var/state/parport/svr_status"
82
83
84int processReq(int sockfd); //Process the request from the client side
85int closesocket(int sockfd);
86void sig_child(int sig);    //signal handler to the dead of child process
87void sig_cleanup(int sig);
88void sig_remove(int sig);//JY1110
89//void checkstatus_usb_par();//JY1110
90int waitsock(int sockfd , int sec , int usec);  //wait to socket until timeout
91void reset_printer(int sec);
92int check_par_usb_prn();//JY: 20031104 change to int from void
93DWORD RECV(int sockfd , PBYTE pRcvbuf , DWORD dwlen , DWORD timeout);
94
95int  fdPRN=0; //File descriptor of the printer port
96char g_useUsb = FALSE;
97char busy = FALSE; //Add by Lisa
98void check_prn_status(char *status_prn, char *cliadd_prn); //Added by Jiahao
99void processReq_Raw(int fd); //Added by Jiahao
100
101static void update_pidfile(void)
102{
103	pid_t pid = getpid();
104	FILE *fp;
105
106	fp = fopen("/var/run/lpdparent.pid", "w");
107	fprintf(fp, "%d", pid);
108	fclose(fp);
109}
110
111/*
112 * logmessage
113 *
114 */
115void logmessage(char *logheader, char *fmt, ...)
116{
117  va_list args;
118  char buf[512];
119
120  va_start(args, fmt);
121
122  vsnprintf(buf, sizeof(buf), fmt, args);
123  openlog(logheader, 0, 0);
124  syslog(0, buf);
125  closelog();
126  va_end(args);
127}
128
129
130
131int main(int argc, char *argv[])
132{
133    int                 sockfd , clisockfd;
134    unsigned int        clilen;
135    int                 childpid;
136    struct sockaddr_in  serv_addr,cli_addr;
137    int err_select;//JY1113
138
139#ifdef LPR_with_ASUS//JY1112
140    int 		LPRflag = 0;
141    fd_set		rfds, afds;
142    int			nfds;
143    int			sockfd_ASUS;
144    unsigned int        clilen_ASUS;
145    int                 childpid_ASUS;
146    struct sockaddr_in  serv_addr_ASUS,cli_addr_ASUS;
147#endif
148#ifdef Raw_Printing_with_ASUS  //Lisa
149	int		netfd, fd, clientlen, one = 1;
150	struct sockaddr_in	netaddr, client;
151#endif
152	int lock;
153	int pid = 0;
154	FILE *fp;
155
156	fp = fopen("/var/run/lpdparent.pid", "r");
157	if (fp) {
158		fscanf(fp, "%d", &pid);
159		fclose(fp);
160	}
161
162	if ((pid > 0) && (kill(pid, 0) == 0 || errno != ESRCH)) {
163		syslog(LOGOPTS, "another lpd daemon exists!!\n");
164		exit(0);
165	}
166
167	update_pidfile();
168
169    //Initial the server the not busy
170    lptstatus.busy = FALSE;
171
172    sigset_t sigs_to_catch;
173    sigemptyset(&sigs_to_catch);
174    sigaddset(&sigs_to_catch, SIGCLD);
175    sigaddset(&sigs_to_catch, SIGINT);
176    sigaddset(&sigs_to_catch, SIGQUIT);
177    sigaddset(&sigs_to_catch, SIGKILL);
178    sigaddset(&sigs_to_catch, SIGUSR2);
179    sigprocmask(SIG_UNBLOCK, &sigs_to_catch, NULL);
180
181    //Setup the signal handler
182    signal(SIGCLD, sig_child);
183    signal(SIGINT, sig_cleanup);
184    signal(SIGQUIT, sig_cleanup);
185    signal(SIGKILL, sig_cleanup);
186    signal(SIGUSR2, sig_remove);//JY1110
187
188    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0 )
189    {
190        syslog(LOGOPTS, "can't open stream socket: %m");
191        exit(0);
192    }
193
194    bzero((char *)&serv_addr , sizeof(serv_addr));
195    serv_addr.sin_family        = AF_INET;
196    serv_addr.sin_addr.s_addr   = htonl(INADDR_ANY);
197    serv_addr.sin_port          = htons(PNT_SVR_PORT_LPR);
198
199
200    if(bind(sockfd,(struct sockaddr *)&serv_addr , sizeof(serv_addr)) < 0 )
201    {
202        syslog(LOGOPTS, "can't bind socket with port %d: %m", PNT_SVR_PORT_LPR);
203        exit(0);
204    }
205    /*JY1111*/
206    int windowsize=2920;
207    setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&windowsize, sizeof(windowsize));
208    int no_delay=1;
209    setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay));	// by Jiahao. 20080808.
210
211    listen(sockfd , 15);
212
213#ifdef Raw_Printing_with_ASUS //Lisa
214	if ((netfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
215	{
216		syslog(LOGOPTS, "cannot open stream socket for raw printing: %m\n");
217		exit(1);
218	}
219	if (setsockopt(netfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
220	{
221		syslog(LOGOPTS, "cannot setsocketopt for raw printing: %m\n");
222		exit(1);
223	}
224	netaddr.sin_family = AF_INET;
225	netaddr.sin_port = htons(BASEPORT);
226	netaddr.sin_addr.s_addr = htonl(INADDR_ANY);
227	memset(netaddr.sin_zero, 0, sizeof(netaddr.sin_zero));
228	if (bind(netfd, (struct sockaddr*) &netaddr, sizeof(netaddr)) < 0)
229	{
230		syslog(LOGOPTS, "cannot bind socket with port %d for raw printing: %m\n", BASEPORT);
231		exit(1);
232	}
233	if (listen(netfd, 5) < 0)
234	{
235		syslog(LOGOPTS, "cannot listen socket for raw printing: %m\n");
236		exit(1);
237	}
238	//clientlen = sizeof(client);
239	//memset(&client, 0, sizeof(client));
240#endif
241
242#ifdef LPR_with_ASUS//JY1112
243	if((sockfd_ASUS = socket(AF_INET,SOCK_STREAM,0)) < 0 )
244	{
245	        syslog(LOG_ERR, "can't open stream socket for LPR: %m");
246	        exit(0);
247	}
248    	bzero((char *)&serv_addr_ASUS , sizeof(serv_addr_ASUS));
249    	serv_addr_ASUS.sin_family        = AF_INET;
250    	serv_addr_ASUS.sin_addr.s_addr   = htonl(INADDR_ANY);
251    	serv_addr_ASUS.sin_port          = htons(PNT_SVR_PORT_ASUS);
252
253    	if(bind(sockfd_ASUS,(struct sockaddr *)&serv_addr_ASUS , sizeof(serv_addr_ASUS)) < 0 )
254    	{
255		syslog(LOG_ERR, "can't bind socket for LPR: %m");
256		exit(0);
257   	}
258
259    	setsockopt(sockfd_ASUS, SOL_SOCKET, SO_RCVBUF, (char *)&windowsize, sizeof(windowsize));
260
261    	listen(sockfd_ASUS , 15);
262
263    	/*set the fds*/
264    	nfds=MAX(sockfd, sockfd_ASUS);
265    	FD_ZERO(&afds);
266#endif
267
268    while(TRUE)
269    {
270	//if (busy) syslog(LOG_NOTICE, "busying %d %d\n", lptstatus.busy, busy);
271
272	lock = file_lock("printer");				// by Jiahao for U2EC. 20080808.
273	if (lptstatus.busy==FALSE && nvram_invmatch("MFP_busy", "2"))
274	{
275		busy=FALSE;
276		nvram_set("MFP_busy", "0");
277
278		nvram_set("u2ec_busyip", "");
279	}
280	file_unlock(lock);
281
282#ifdef Raw_Printing_with_ASUS //Lisa
283	FD_SET(netfd, &afds);
284#endif
285#ifdef LPR_with_ASUS//JY1112
286	FD_SET(sockfd, &afds);
287	FD_SET(sockfd_ASUS, &afds);
288	memcpy(&rfds, &afds, sizeof(rfds));
289
290	if((err_select=select(nfds+1, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0 )) < 0)
291	{
292//JY1120	printf("select error on sockfd: error=%d\n", errno);
293		/**/
294//		printf("sockfd_FD_ISSET=%d\n", FD_ISSET(sockfd, &rfds));
295//JY1120		printf("sockfd_ASUS FD_ISSET=%d\n", FD_ISSET(sockfd_ASUS, &rfds));
296		/**/
297//		if(errno != 4)//JY1113: delete
298		//syslog(LOG_NOTICE, "select error %d\n", err_select);
299		continue;
300	}
301#endif
302        clilen = sizeof(cli_addr);
303
304	if(FD_ISSET(sockfd_ASUS, &rfds))
305	{
306		LPRflag = 0;
307		clisockfd   = accept(sockfd_ASUS,(struct sockaddr *)&cli_addr, &clilen);
308	}
309#ifdef LPR_with_ASUS//JY1112
310	else if(FD_ISSET(sockfd, &rfds))
311	{
312		LPRflag = 1;
313		clisockfd   = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen);
314	}
315#endif
316#ifdef Raw_Printing_with_ASUS //Lisa
317//	else if(FD_ISSET(netfd, &rfds) && busy==FALSE)
318	else if(FD_ISSET(netfd, &rfds))
319	{
320		lock = file_lock("printer");	// by Jiahao for U2EC. 20080808.
321		if (nvram_match("MFP_busy", "0"))
322		{
323			file_unlock(lock);
324			LPRflag = 2;
325			clisockfd = accept(netfd, (struct sockaddr*) &cli_addr, &clilen);
326		}
327		else
328		{
329			file_unlock(lock);
330			sleep(2);
331			continue;
332		}
333	}
334#endif
335	else
336        {
337		//syslog(LOG_NOTICE, "No select\n");
338		sleep(2);
339		continue;
340	}
341
342	strcpy(clientaddr , inet_ntoa(cli_addr.sin_addr));
343
344	if(clisockfd < 0)
345        {
346	     //syslog(LOG_NOTICE, "LPD error: No clisockfd %d\n", LPRflag);
347             continue;
348        }
349
350	lock = file_lock("printer");
351//	if (busy!=FALSE)	/* 2004/09/10 by Joey, process nack in parent for LPR and Remote Prot */
352	if (nvram_invmatch("MFP_busy", "0"))		// by Jiahao for U2EC. 20080808.
353	{
354		file_unlock(lock);
355		//syslog(LOG_NOTICE, "Printing others 1 %d %d\n", LPRflag, clisockfd);
356		if (LPRflag==0) processReq(clisockfd);
357		else if (LPRflag==1) processReq_LPR(clisockfd, 0);
358		//syslog(LOG_NOTICE, "Printing others %d %d\n", LPRflag, clisockfd);
359		close(clisockfd);
360		// For Raw printing, don't resonse to client while busy
361		sleep(5);
362		continue;
363	}
364
365	nvram_set("MFP_busy", "1");
366
367	if (nvram_match("lan_ipaddr_t", ""))
368		nvram_set("u2ec_busyip", nvram_safe_get("lan_ipaddr"));
369	else
370		nvram_set("u2ec_busyip", nvram_safe_get("lan_ipaddr_t"));
371
372	file_unlock(lock);
373
374        if( (childpid = fork() ) < 0)
375        {
376        }
377        else if(childpid == 0)
378        {
379		//syslog(LOG_NOTICE, "Printing %d\n", LPRflag);
380
381		if(LPRflag==0) processReq(clisockfd);
382#ifdef LPR_with_ASUS//JY1114
383		else if(LPRflag==1) processReq_LPR(clisockfd, 1);
384#endif
385#ifdef Raw_Printing_with_ASUS //Lisa
386		else if(LPRflag == 2) processReq_Raw(clisockfd);
387#endif
388		close(sockfd);
389		close(sockfd_ASUS);
390		close(netfd);
391        	exit(0);
392        }
393
394	//syslog(0, "Printing Process %d %d %d\n", busy, lptstatus.busy, childpid);
395
396        //parents process goes on here
397        //remark PRINT("fork -- childpid %d\n",childpid);
398
399	if(lptstatus.busy == FALSE)
400	{
401		lptstatus.busy = TRUE;
402//		busy = TRUE;				// remarked by Jiahao for U2EC. 20080808.
403		strcpy(lptstatus.addr , inet_ntoa(cli_addr.sin_addr));
404		lptstatus.pid = childpid;
405	}
406
407        close(clisockfd);
408    }
409
410}
411
412
413int processReq(int sockfd)
414{
415
416    char                recv_buf[4]; //buffer to receive header
417    static char         waittime = 1;
418    int                 iCount;
419    struct print_buffer pbuf;
420    char                chPortOpened = FALSE;
421
422    /***************************************/
423    /**  We reset the printer only when   **/
424    /**  user wants to cancel a job or    **/
425    /**  error occurs                     **/
426    /***************************************/
427
428    //Process the request from cleint
429    //return when error or job complete
430    while(TRUE)
431    {
432        LPT_CMD_PKT_HDR     *pHdrCmd  = NULL;
433        LPT_DATA_PKT_HDR    *pHdrData = NULL;
434        LPT_RES_PKT_HDR     pktRes;
435        WORD                body[1];
436        int                 rcv; //records how many bytes being received
437        char                *para_buf = NULL; //buffer to store parameter
438
439        memset(recv_buf,0,sizeof(recv_buf));
440        iCount = sizeof(recv_buf);
441
442        if(waittime < 5)
443        {
444            waittime ++;
445        }
446
447        //Receive the complete header here
448        while( iCount > 0 )
449        {
450            rcv = RECV(sockfd , recv_buf + (4 - iCount) , iCount , 60);
451
452            if( rcv < 1)
453            {
454                //receive error
455                //PRINT("1. rcv -> %d\n",rcv);
456
457                if(rcv < 0)
458                {
459                	//perror("ERR:");
460                }
461
462                closesocket(sockfd);
463                if(chPortOpened == TRUE)
464                {
465                    reset_printer(10);
466                }
467
468                return 0;
469            }
470
471            iCount = iCount - rcv;
472        }
473
474
475        //Check Service ID
476
477        switch(recv_buf[0])
478        {
479            case NET_SERVICE_ID_LPT_EMU:
480                //PRINT("Service ID -> NET_SERVICE_ID_LPT_EMU \n");
481                break;
482
483            default:
484                //PRINT("Service ID -> Not Supported \n");
485                closesocket(sockfd);
486                if(chPortOpened == TRUE)
487                {
488                    reset_printer(10);
489                }
490                return(0);
491                break;
492        }
493
494
495        //Check Packet Type
496
497        switch(recv_buf[1])
498        {
499            case NET_PACKET_TYPE_CMD:
500                //PRINT(">>> TYPE_CMD ");
501                pHdrCmd = (LPT_CMD_PKT_HDR *)recv_buf;
502                break;
503
504            case NET_PACKET_TYPE_RES:
505                //We should not recevice Response Packet in Server
506                //PRINT("Packet Type -> NET_PACKET_TYPE_RES Error!!! \n");
507                closesocket(sockfd);
508                if(chPortOpened == TRUE)
509                {
510                    reset_printer(10);
511                }
512                return(0);
513                break;
514
515            case NET_PACKET_TYPE_DATA:
516                //PRINT("$$$ TYPE_DATA ");
517                pHdrData = (LPT_DATA_PKT_HDR *)recv_buf;
518                break;
519
520            default:
521                //PRINT("Packet Type -> Not Supported \n");
522                closesocket(sockfd);
523                if(chPortOpened == TRUE)
524                {
525                    reset_printer(10);
526                }
527                return(0);
528                break;
529
530        }
531
532        if( pHdrCmd != NULL)
533        {
534            //We receive command
535
536            para_buf = NULL;
537
538            iCount = pHdrCmd->ParaLength;
539
540	    if (iCount!=0)
541	    {
542             	para_buf = (char *)malloc(pHdrCmd->ParaLength);
543            }
544
545	    //PRINT("HdrCmd Length %d\n", iCount);
546
547	    // para_buf may be NULL but this command still work
548	    // 2004/06/07 by Joey
549            if(iCount!=0 && para_buf == NULL)
550            {
551                //perror("malloc error 1:");
552                closesocket(sockfd);
553                if(chPortOpened == TRUE)
554                {
555                    reset_printer(10);
556                }
557                return(0);
558            }
559
560            while( iCount > 0 )
561            {
562                rcv = RECV(sockfd , (para_buf + (pHdrCmd->ParaLength - iCount )) , iCount , 30);
563
564                if( rcv < 1)
565                {
566                    //receive error
567                    //perror("2. RECV ERR:");
568                    closesocket(sockfd);
569                    free(para_buf);
570                    if(chPortOpened == TRUE)
571                    {
572                        reset_printer(10);
573                    }
574                    return 0;
575                }
576
577                iCount = iCount - rcv;
578            }
579
580
581            switch(pHdrCmd->CommandID)
582            {
583                case NET_CMD_ID_OPEN:
584                    //remark PRINT("NET_CMD_ID_OPEN\n");
585
586                    /************************************/
587                    /************************************/
588                    /*** TODO: add code here to check ***/
589                    /*** the printer status           ***/
590                    /************************************/
591                    /************************************/
592
593                    pktRes.ServiceID = NET_SERVICE_ID_LPT_EMU;
594                    pktRes.PacketType = NET_PACKET_TYPE_RES;
595                    pktRes.CommandID = NET_CMD_ID_OPEN;
596                    pktRes.ResLength = 2;
597
598                    if(busy == FALSE)
599                    {
600                        int prnstatus=0;
601		        FILE *statusFp = NULL;
602
603
604                        //remark PRINT("--------lptstatus.busy == FALSE\n");
605
606                        /* add by James Yeh to support usb printer */
607                        /* 2002/12/25 							   */
608
609
610                        check_par_usb_prn();
611
612                        //Open printer port -modified by PaN
613                        if(g_useUsb == TRUE)
614                        {
615                        	fdPRN = open("/dev/usb/lp0",O_RDWR);
616                        }
617                        else
618                        {
619                        	fdPRN = open("/dev/lp0",O_RDWR);
620                        }
621
622                        if(fdPRN == 0)
623                        {
624                            //Failed to open printer port
625                            //PRINT("Can not open lp0 errno -> %d \n",errno);
626                            //perror("ERR:");
627
628                            //Send header
629                            send(sockfd , (const char *)&pktRes , sizeof(pktRes) , 0);
630                            //Send body
631                            body[0] = ERR_SERVER_LPT_FAIL;
632                            send(sockfd , body , sizeof(body) , 0);
633                            free(para_buf);
634                            return(0);
635                        }
636
637                        ioctl(fdPRN,LPGETSTATUS,&prnstatus);
638
639                        if(prnstatus != 0)
640                        {
641                            //remark PRINT("prnstatus != 0\n");
642                            body[0] = ERR_SERVER_OCCUPIED;
643
644                            /*******************************************************************************/
645                            /* why we are using ERR_SERVER_OCCUPIED instead of ERR_SERVER_LPT_FAIL here ?? */
646                            /* Because ERR_SERVER_OCCUPIED will let user try again & again. Using          */
647                            /* ERR_SERVER_LPT_FAIL will fail the reques                                    */
648                            /*******************************************************************************/
649
650                            //Send header
651                            send(sockfd , (const char *)&pktRes , sizeof(pktRes) , 0);
652                            //Send body
653                            send(sockfd , body , sizeof(body) , 0);
654                            free(para_buf);
655                            return(0);
656                        }
657
658			            statusFp = fopen(STATUS_FILE , "w");
659
660            			if(statusFp != NULL)
661            			{
662                			fprintf(statusFp,"PRN_CLIENT=\"%s\"\n",lptstatus.addr);
663                			fclose(statusFp);
664            			}
665            			else
666            			{
667                			//perror("Open status file failed: ");
668            			}
669
670                        chPortOpened = TRUE;
671
672                        body[0] = ERR_SUCCESS;
673                    }
674                    else
675                    {
676                        //PRINT("*********lptstatus.busy == TRUE\n");
677                        body[0] = ERR_SERVER_OCCUPIED;
678
679                        //Send header
680                        send(sockfd , (const char *)&pktRes , sizeof(pktRes) , 0);
681                        //Send body
682                        send(sockfd , body , sizeof(body) , 0);
683                        free(para_buf);
684                        return(0);
685                    }
686
687                    //Send header
688                    send(sockfd , (const char *)&pktRes , sizeof(pktRes) , 0);
689                    //Send body
690                    send(sockfd , body , sizeof(body) , 0);
691
692                    break;
693
694                case NET_CMD_ID_CLOSE:
695                {
696                    char bCancel = FALSE;
697
698
699                    //remark PRINT("NET_CMD_ID_CLOSE\n");
700
701                    /*****************************************************/
702                    /* Check if user normally or abnormally end this job */
703                    /*                                 James 2002/06/05  */
704                    /*****************************************************/
705
706                    if(pHdrCmd->ParaLength != 1) //Length should be 1 byte long
707                    {
708                        //remark PRINT("NET_CMD_ID_CLOSE length error -- %d\n",pHdrCmd->ParaLength);
709                        closesocket(sockfd);
710                        free(para_buf);
711                        if(chPortOpened == TRUE)
712                        {
713                            reset_printer(10);
714                        }
715                        return(0);
716                    }
717
718                    //remark PRINT("para_buf[0] - %02X\n",para_buf[0]);
719
720                    if(para_buf[0] == 1)
721                    {
722                        bCancel = TRUE;
723                    }
724
725
726                    pktRes.ServiceID = NET_SERVICE_ID_LPT_EMU;
727                    pktRes.PacketType = NET_PACKET_TYPE_RES;
728                    pktRes.CommandID = NET_CMD_ID_CLOSE;
729                    pktRes.ResLength = 2;
730
731
732                    //Send header
733                    send(sockfd , (const char *)&pktRes , sizeof(pktRes) , 0);
734
735                    //Send body
736                    body[0] = ERR_SUCCESS;
737                    send(sockfd , body , sizeof(body) , 0);
738
739                    closesocket(sockfd);
740                    free(para_buf);
741
742                    //close printer port modified by PaN
743                    sleep(1);
744
745                    if(bCancel == TRUE)
746                    {
747                        //reset printer
748                        //PRINT("Reset Printer\n");
749                        reset_printer(10);
750                    }
751
752                    close(fdPRN);
753
754                    return(0);
755                    break;
756                }//case NET_CMD_ID_CLOSE:
757
758                case NET_CMD_ID_READ:
759                {
760                    LPT_DATA_PKT_HDR    pktData;
761                    WORD                len;
762                    int                 res_fread = 0;
763                    PBYTE               pReadbuf;
764
765                    len = (para_buf[1] << 8) + para_buf[0];
766
767                    //remark PRINT("NET_CMD_ID_READ len -> %d\n",len);
768
769                    /************************************/
770                    /************************************/
771                    /*** TODO: add code here to read  ***/
772                    /*** the printer port             ***/
773                    /************************************/
774                    /************************************/
775
776                    pReadbuf = (char *)malloc(len + 1);
777
778                    if(pReadbuf == NULL)
779                    {
780                        //perror("malloc error 2:");
781                        closesocket(sockfd);
782                        free(para_buf);
783                        if(chPortOpened == TRUE)
784                        {
785                            reset_printer(10);
786                        }
787                        return(0);
788                    }
789
790                    pbuf.len = len;
791                    pbuf.buf = pReadbuf;
792                    //PRINT("Start Read\n");
793                    res_fread = ioctl(fdPRN,LPREADDATA,&pbuf);
794                    //PRINT("End Read\n");
795                    //PRINT("---- res_fread %d\n",res_fread);
796
797                    if(res_fread > 0)
798                    {
799                        len = res_fread;
800                        pReadbuf[res_fread]= 0;
801                        //PRINT("*** %s\n",pReadbuf);
802                    }
803                    else
804                    {
805                        len = 0;
806                    }
807
808                    pktData.ServiceID = NET_SERVICE_ID_LPT_EMU;
809                    pktData.PacketType = NET_PACKET_TYPE_DATA;
810                    pktData.DataLength = len; //can not exceed 0xFFFF
811
812                    /**********    Sending Header     **********/
813                    send(sockfd , (const char *)&pktData , sizeof(pktData) , 0);
814
815                    if( len > 0)
816                    {
817                        /**********    Sending Body       **********/
818                        send(sockfd , (const char *)pReadbuf , len , 0);
819                    }
820                    free(pReadbuf);
821
822                    break;
823                }
824
825                free(para_buf);
826            }//switch(pHdrCmd->CommandID)
827        }//if( pHdrCmd != NULL)
828
829
830        if( pHdrData != NULL)
831        {
832            //We receive Data
833            int     res_fwrite;
834            int     res_total_fwrite;
835            int     write_len;
836            int     total_len;
837            PBYTE   write_buf;
838            int prnstatus=0;
839
840            iCount = pHdrData->DataLength;
841
842            if (iCount!=0)
843	    {
844            	para_buf = (char *)malloc(pHdrData->DataLength);
845            }
846            //remark
847	    //PRINT("pHdrData->DataLength -- %d\n",pHdrData->DataLength);
848
849            if(iCount!=0 && para_buf == NULL)
850            {
851                //perror("malloc error 3:");
852                closesocket(sockfd);
853                if(chPortOpened == TRUE)
854                {
855                    reset_printer(10);
856                }
857                return(0);
858            }
859
860            //PRINT("DATA HDR OK...\n");
861
862            while( iCount > 0 )
863            {
864                rcv = RECV(sockfd , (para_buf + (pHdrData->DataLength - iCount )) , iCount , 30);
865
866                if( rcv < 1)
867                {
868                    //receive error
869                    //perror("3. RECV ERR:");
870                    closesocket(sockfd);
871                    free(para_buf);
872                    if(chPortOpened == TRUE)
873                    {
874                        reset_printer(10);
875                    }
876                    return 0;
877                }
878
879                iCount = iCount - rcv;
880            }
881
882
883            //PRINT("DATA BODY OK...\n");
884
885            pbuf.len = pHdrData->DataLength;
886            pbuf.buf = para_buf;
887
888            write_len = 0;
889            total_len = pHdrData->DataLength;
890            write_buf = para_buf;
891            res_fwrite = 0;
892            res_total_fwrite = 0;
893
894            //remark PRINT("total_len %d\n",total_len);
895
896            while(total_len > 0)
897            {
898                if(total_len > 4096)
899                {
900                    pbuf.len = 4096;
901                    pbuf.buf = write_buf;
902                    res_fwrite = ioctl(fdPRN,LPWRITEDATA,&pbuf);
903
904                    if(res_fwrite != 4096)
905                    {
906                        DWORD retry = 0;
907
908                        ioctl(fdPRN,LPGETSTATUS,&prnstatus);
909
910                        //remark PRINT("prnstatus %d\n",prnstatus);
911
912                        while( ((prnstatus == 0) || (prnstatus & LP_PBUSY)) && (res_fwrite != 4096) && (retry < 3))
913                        {
914                            //remark PRINT("}}}}}}}}}}}} res_fwrite %d\n",res_fwrite);
915                            pbuf.len = 4096 - res_fwrite;
916                            pbuf.buf = &(write_buf[res_fwrite]);
917                            //usleep(500); //why we don't use usleep here ?? becuse usleep will sleep longer then we expect in iBox
918                            sleep(1);
919                            res_fwrite = res_fwrite + ioctl(fdPRN,LPWRITEDATA,&pbuf);
920                            //remark PRINT("}}}}}}}}}}}} res_fwrite %d\n",res_fwrite);
921                            ioctl(fdPRN,LPGETSTATUS,&prnstatus);
922
923                            //remark PRINT("retry %d\n",retry);
924                            retry ++;
925                        }
926
927                    }
928
929                    res_total_fwrite = res_total_fwrite + res_fwrite;
930
931                    if(res_fwrite != 4096)
932                    {
933                        break;
934                    }
935                    else
936                    {
937                        total_len = total_len - 4096;
938                        if(total_len == 0)
939                        {
940                            //remark PRINT("total_len == 0 \n");
941                            break;
942                        }
943                        write_buf = &(write_buf[4096]);
944                    }
945
946                    //remark PRINT("res_total_fwrite %d -- res_fwrite %d \n",res_total_fwrite,res_fwrite);
947
948                }
949                else
950                {
951                    pbuf.len = total_len;
952                    pbuf.buf = write_buf;
953                    res_fwrite = ioctl(fdPRN,LPWRITEDATA,&pbuf);
954
955                    //remark PRINT("PPPPPPP res_fwrite %d\n",res_fwrite);
956                    if(res_fwrite != total_len)
957                    {
958                        DWORD retry = 0;
959
960                        ioctl(fdPRN,LPGETSTATUS,&prnstatus);
961                        //remark PRINT("prnstatus %d\n",prnstatus);
962
963                        while( ((prnstatus == 0) || (prnstatus & LP_PBUSY))  && (res_fwrite != total_len) && (retry < 3))
964                        {
965                            pbuf.len = total_len - res_fwrite;
966                            pbuf.buf = &(write_buf[res_fwrite]);
967                            //usleep(500); //why we don't use usleep here ?? becuse usleep will sleep longer then we expect in iBox
968                            sleep(1);
969                            res_fwrite = res_fwrite + ioctl(fdPRN,LPWRITEDATA,&pbuf);
970                            //remark PRINT("}}}}}}}}}}}} res_fwrite %d\n",res_fwrite);
971                            ioctl(fdPRN,LPGETSTATUS,&prnstatus);
972                            //remark PRINT("retry %d\n",retry);
973                            retry ++;
974                        }
975
976                    }
977
978                    res_total_fwrite = res_total_fwrite + res_fwrite;
979                    //remark PRINT("res_total_fwrite %d -- res_fwrite %d \n",res_total_fwrite,res_fwrite);
980                    break;
981                }
982
983            }
984
985
986            //remark PRINT("WritePrint %d - %d bytes\n",res_total_fwrite,pHdrData->DataLength);
987
988            if(res_total_fwrite != pHdrData->DataLength)
989            {
990                int tmp=0;
991                //remark PRINT("res_total_fwrite != pHdrData->DataLength \n");
992                ioctl(fdPRN,LPGETSTATUS,&prnstatus);
993
994                //remark PRINT("prnstatus %08X \n",prnstatus);
995
996                if((prnstatus & LP_PERRORP) == 1 ) //Printer off-line
997                {
998                    //remark PRINT("Printer off-line -- prnstatus %d\n",prnstatus);
999                    res_total_fwrite = res_total_fwrite|0x8000;
1000                }
1001                else
1002                {
1003                    //remark PRINT("Paper Empty -- prnstatus %d\n",prnstatus);
1004                    res_total_fwrite = res_total_fwrite|0x4000;
1005                }
1006		check_prn_status("BUSY or ERROR", clientaddr);
1007            }
1008            else{//JY1113 add
1009/*JY1113*/
1010		check_prn_status("Printing", clientaddr);
1011/**/
1012            }
1013            //remark PRINT("res_total_fwrite %08X\n",res_total_fwrite);
1014
1015            body[0] = res_total_fwrite;
1016
1017            pktRes.ServiceID = NET_SERVICE_ID_LPT_EMU;
1018            pktRes.PacketType = NET_PACKET_TYPE_RES;
1019            pktRes.CommandID = NET_CMD_ID_DATA_RES;
1020            pktRes.ResLength = 2;
1021
1022            //Send header
1023            send(sockfd , (const char *)&pktRes , sizeof(pktRes) , 0);
1024
1025            //Send body
1026            send(sockfd , body , sizeof(body) , 0);
1027
1028            free(para_buf);
1029        }//if( pHdrData != NULL)
1030    }
1031    //remark PRINT("Thread Over\n");
1032
1033    return(0);
1034
1035}
1036
1037
1038void sig_child(int sig)
1039{
1040    int childpid;
1041
1042    childpid = waitpid(-1, NULL , WNOHANG);
1043
1044    while( childpid > 0)
1045    {
1046
1047	//syslog(LOG_NOTICE, "sig child: %d\n", childpid);
1048    	//remark PRINT("sig_child %d\n",childpid);
1049
1050	    if( lptstatus.pid == childpid )
1051    	{
1052	        FILE *statusFp = NULL;
1053
1054        	statusFp = fopen(STATUS_FILE , "w");
1055
1056        	if(statusFp != NULL)
1057        	{
1058            		fprintf(statusFp,"PRN_CLIENT=\"\"\n");
1059            		fclose(statusFp);
1060        	}
1061        	else
1062        	{
1063            		//perror("Open status file failed: ");
1064        	}
1065
1066
1067    	    	/*** Wait 10 seconds here      ***/
1068        	/*** Because some slow printer ***/
1069        	/*** need some time to consume ***/
1070        	/*** the data...               ***/
1071        	sleep(10);
1072
1073        	lptstatus.busy = FALSE;
1074        	lptstatus.pid  = 0;
1075		check_prn_status(ONLINE, "");
1076
1077    	}
1078
1079    	childpid = waitpid(-1, NULL , WNOHANG);
1080	}
1081
1082   	//remark PRINT("waitpid -- childpid%d\n",childpid);
1083
1084}
1085
1086void sig_cleanup(int sig)
1087{
1088    //remark PRINT("sig_cleanup\n");
1089    exit(0);
1090}
1091
1092//JY1110
1093void sig_remove(int sig)
1094{
1095	if(lptstatus.pid != 0){
1096		kill(lptstatus.pid, SIGKILL);
1097	}
1098	else
1099		return;
1100}
1101
1102
1103int closesocket(int sockfd)
1104{
1105    //shutdown(sockfd,SHUT_RDWR);
1106    close(sockfd);
1107}
1108
1109/************************************/
1110/***  Receive the socket          ***/
1111/***  with a timeout value        ***/
1112/************************************/
1113DWORD RECV(int sockfd , PBYTE pRcvbuf , DWORD dwlen , DWORD timeout)
1114{
1115
1116    if( waitsock(sockfd , timeout , 0) == 0)
1117    {
1118        //timeout
1119        PRINT("RECV timeout %d\n",timeout);
1120        return -1;
1121    }
1122
1123    return recv(sockfd , pRcvbuf  , dwlen , 0 );
1124}
1125
1126
1127int waitsock(int sockfd , int sec , int usec)
1128{
1129    struct timeval  tv;
1130    fd_set          fdvar;
1131    int             res;
1132
1133    FD_ZERO(&fdvar);
1134    FD_SET(sockfd, &fdvar);
1135
1136    tv.tv_sec  = sec;
1137    tv.tv_usec = usec;
1138
1139    res = select( sockfd + 1 , &fdvar , NULL , NULL , &tv);
1140
1141    return res;
1142}
1143
1144void reset_printer(int sec)
1145{
1146    sleep(sec);
1147    ioctl(fdPRN,LPRESET);
1148}
1149
1150
1151/* to check use usb or parport printer */
1152/* James Yeh 2002/12/25 02:13	       */
1153int check_par_usb_prn()//JY: 20031104 change to int from void
1154{
1155    char    buf[1024];
1156    char    *token;
1157    FILE    *fp;
1158
1159#ifdef USBONLY
1160    g_useUsb = TRUE;
1161    return(g_useUsb);
1162#else
1163    fp=fopen("/proc/sys/dev/parport/parport0/devices/lp/deviceid","r");
1164
1165    if( fp != NULL)
1166    {
1167        while ( fgets(buf, sizeof(buf), fp) != NULL )
1168        {
1169            if(buf[0] == '\n')
1170            {
1171                //PRINT("skip empty line\n");
1172                continue;
1173            }
1174
1175            if(strncmp(buf , "status: " , strlen("status: "))   == 0)
1176            {
1177                token= buf + strlen("status: ");
1178
1179                //PRINT("token[0] %d\n",token[0]);
1180
1181//printf("token=%s\n", token);//JY1104
1182                if(token[0] == '0')
1183                {
1184                    g_useUsb = TRUE;
1185//printf("USB\n");//JY1112: delete
1186                }
1187                else
1188                {
1189                    g_useUsb = FALSE;
1190//printf("PARALLEL\n");//JY1112: delete
1191                }
1192			return(g_useUsb);//JY: 1104
1193                break;
1194            }
1195
1196        }
1197
1198        fclose(fp);
1199    }
1200#endif
1201
1202}
1203
1204/*1110test status
1205void checkstatus_usb_par()
1206{
1207	if(fd_print <= 0 || fd_print == NULL){
1208		check_prn_status("Off-line", "");
1209	}
1210	else {
1211		check_prn_status(ONLINE, "");
1212	}
1213}
1214*/
1215
1216/*JY1114: check printer status*/
1217void check_prn_status(char *status_prn, char *cliadd_prn)
1218{
1219	STATUSFILE=fopen("/var/state/printstatus.txt", "w");
1220	if(cliadd_prn == NULL)
1221	{
1222		fprintf(STATUSFILE, "PRINTER_USER=\"\"\n");
1223	}
1224	else
1225	{
1226		fprintf(STATUSFILE, "PRINTER_USER=\"%s\"\n", cliadd_prn);
1227	}
1228	fprintf(STATUSFILE, "PRINTER_STATUS=\"%s\"\n", status_prn);
1229	fclose(STATUSFILE);
1230	//strcpy(printerstatus, status_prn);
1231}
1232/*JY1114: get printer queue name for LPR*/
1233int get_queue_name(char *input)
1234{
1235	char QueueName_got[32];
1236	char *index1;
1237	int rps_i=0, rps_j=0;
1238	while(index1 = strrchr(input, ' '))
1239		index1[0] = 0;
1240	rps_i = 0;
1241	strcpy(QueueName_got, input);
1242	//return(strcmp(QueueName_got, "LPRServer"));
1243	//by pass queue Name Check
1244	return 0;
1245}
1246
1247/*JY1120: send ack*/
1248void send_ack_packet(int *talk, int ack)
1249{
1250	char buffertosend[SMALLBUFFER];
1251	buffertosend[0] = ack;
1252	buffertosend[1] = 0;
1253	//printf("send_ack_packet...\n");//JY1120: delete
1254	if( write( *talk, buffertosend, strlen(buffertosend) ) < 0 )
1255	{
1256		//printf("send_ack_packet: can not write socket...\n");
1257	}
1258}
1259
1260/*#######Lisa: Raw printing##########
1261 * open printer()
1262 * copy stream()
1263 * ProcessReq_Raw()
1264 ##################################*/
1265int open_printer(void)
1266{
1267        int		f;
1268
1269	check_par_usb_prn();
1270	if(g_useUsb==TRUE)
1271	{
1272		if ((f=open("/dev/usb/lp0",O_RDWR)) < 0 )
1273		{
1274			syslog(LOGOPTS, "cannot open /dev/usb/lp0: %m\n");
1275			exit(1);
1276		}
1277	}
1278	else
1279	{
1280		if ((f=open("dev/lp0",O_RDWR)) < 0)
1281		{
1282//			syslog(LOGOPTS, "Open Parallel port error");
1283			exit(1);
1284		}
1285	}
1286	return (f);
1287}
1288
1289int copy_stream(int fd,int f)
1290{
1291	int		nread,nwrite;
1292	char		buffer[8192];
1293	int 		timeout=20, wait;
1294	int 		busyflag=0;
1295
1296	//PRINT("copy_stream\n");
1297	while ((nread = read(fd, buffer, sizeof(buffer))) > 0)
1298	{
1299		int index=0,countread;
1300
1301		// nwrite=fwrite(buffer, sizeof(char), nread, f);
1302                /* Lisa:fwrite => write */
1303 		check_prn_status("Printing", clientaddr);  //Add by Lisa
1304
1305		while	(index < nread )
1306		{
1307			countread=nread-index;
1308			nwrite=write(f, &buffer[index],countread);
1309
1310			if (nwrite<0)
1311			{
1312	     			logmessage("lpd", "write error : %d\n", errno);
1313				check_prn_status("Busy or Error", clientaddr);
1314				return(nread);
1315			}
1316#ifdef REMOVE
1317			else if (nwrite==0)
1318			{
1319	     			syslog(LOG_NOTICE, "write error 4: %d\n", nwrite);
1320				check_prn_status("Busy or Error",clientaddr);
1321				busyflag=1;
1322			}
1323#endif
1324			else if ((wait=waitsock(f,timeout,0))==0)
1325			{
1326	     			//logmessage("lpd", "write error %d\n", errno);
1327				check_prn_status("Busy or Error",clientaddr);
1328				busyflag=1;
1329			}
1330			else if(wait<0)
1331			{
1332	     			logmessage("lpd", "can not write : %d\n", errno);
1333				check_prn_status("Busy or Error",clientaddr);
1334				return(nread);
1335			}
1336			else
1337			{
1338				index+=nwrite;
1339
1340				if (busyflag==1)
1341				{
1342					busyflag = 0;
1343					check_prn_status("Printing",clientaddr);
1344				}
1345			}
1346		}
1347	}
1348	//(void)fflush(f);
1349        check_prn_status(ONLINE,""); //Add by Lisa
1350	return (nread);
1351}
1352
1353void processReq_Raw(int fd)
1354{
1355	int f1;
1356
1357	if (busy == FALSE)
1358	{
1359		if ((f1 = open_printer()) >= 0)   //modify by Lisa
1360		{
1361			if (copy_stream(fd, f1) < 0)
1362			{
1363				//syslog(0, "copy stream err\n");
1364			}
1365			close(f1);
1366		}
1367	}
1368	close(fd);
1369}
1370