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