printjob.c (86935) | printjob.c (94032) |
---|---|
1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 29 unchanged lines hidden (view full) --- 38 The Regents of the University of California. All rights reserved.\n"; 39#endif /* not lint */ 40 41#ifndef lint 42/* 43static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95"; 44*/ 45static const char rcsid[] = | 1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 29 unchanged lines hidden (view full) --- 38 The Regents of the University of California. All rights reserved.\n"; 39#endif /* not lint */ 40 41#ifndef lint 42/* 43static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95"; 44*/ 45static const char rcsid[] = |
46 "$FreeBSD: head/usr.sbin/lpr/lpd/printjob.c 86935 2001-11-27 01:32:25Z gad $"; | 46 "$FreeBSD: head/usr.sbin/lpr/lpd/printjob.c 94032 2002-04-07 05:37:27Z gad $"; |
47#endif /* not lint */ 48 49 50/* 51 * printjob -- print jobs in the queue. 52 * 53 * NOTE: the lock file is used to pass information to lpq and lprm. 54 * it does not need to be removed because file locks are dynamic. --- 70 unchanged lines hidden (view full) --- 125#define TFILENAME "fltXXXXXX" 126static char tfile[] = TFILENAME; /* file name for filter output */ 127 128static void abortpr(int _signo); 129static void alarmhandler(int _signo); 130static void banner(struct printer *_pp, char *_name1, char *_name2); 131static int dofork(const struct printer *_pp, int _action); 132static int dropit(int _c); | 47#endif /* not lint */ 48 49 50/* 51 * printjob -- print jobs in the queue. 52 * 53 * NOTE: the lock file is used to pass information to lpq and lprm. 54 * it does not need to be removed because file locks are dynamic. --- 70 unchanged lines hidden (view full) --- 125#define TFILENAME "fltXXXXXX" 126static char tfile[] = TFILENAME; /* file name for filter output */ 127 128static void abortpr(int _signo); 129static void alarmhandler(int _signo); 130static void banner(struct printer *_pp, char *_name1, char *_name2); 131static int dofork(const struct printer *_pp, int _action); 132static int dropit(int _c); |
133static int execfilter(struct printer *_pp, char *_f_cmd, char **_f_av, 134 int _infd, int _outfd); |
|
133static void init(struct printer *_pp); 134static void openpr(const struct printer *_pp); 135static void opennet(const struct printer *_pp); 136static void opentty(const struct printer *_pp); 137static void openrem(const struct printer *pp); 138static int print(struct printer *_pp, int _format, char *_file); 139static int printit(struct printer *_pp, char *_file); 140static void pstatus(const struct printer *_pp, const char *_msg, ...) --- 825 unchanged lines hidden (view full) --- 966 * Send a data file to the remote machine and spool it. 967 * Return positive if we should try resending. 968 */ 969static int 970sendfile(struct printer *pp, int type, char *file, char format) 971{ 972 register int f, i, amt; 973 struct stat stb; | 135static void init(struct printer *_pp); 136static void openpr(const struct printer *_pp); 137static void opennet(const struct printer *_pp); 138static void opentty(const struct printer *_pp); 139static void openrem(const struct printer *pp); 140static int print(struct printer *_pp, int _format, char *_file); 141static int printit(struct printer *_pp, char *_file); 142static void pstatus(const struct printer *_pp, const char *_msg, ...) --- 825 unchanged lines hidden (view full) --- 968 * Send a data file to the remote machine and spool it. 969 * Return positive if we should try resending. 970 */ 971static int 972sendfile(struct printer *pp, int type, char *file, char format) 973{ 974 register int f, i, amt; 975 struct stat stb; |
974 FILE *fp; 975 char buf[BUFSIZ]; 976 int closedpr, resp, sizerr, statrc; | 976 char *av[15], *filtcmd; 977 char buf[BUFSIZ], opt_c[4], opt_h[4], opt_n[4]; 978 int filtstat, narg, resp, sizerr, statrc; |
977 978 statrc = lstat(file, &stb); 979 if (statrc < 0) { 980 syslog(LOG_ERR, "%s: error from lstat(%s): %m", 981 pp->printer, file); 982 return(ERROR); 983 } 984 f = open(file, O_RDONLY); --- 6 unchanged lines hidden (view full) --- 991 * Check to see if data file is a symbolic link. If so, it should 992 * still point to the same file or someone is trying to print something 993 * he shouldn't. 994 */ 995 if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && 996 (stb.st_dev != fdev || stb.st_ino != fino)) 997 return(ACCESS); 998 | 979 980 statrc = lstat(file, &stb); 981 if (statrc < 0) { 982 syslog(LOG_ERR, "%s: error from lstat(%s): %m", 983 pp->printer, file); 984 return(ERROR); 985 } 986 f = open(file, O_RDONLY); --- 6 unchanged lines hidden (view full) --- 993 * Check to see if data file is a symbolic link. If so, it should 994 * still point to the same file or someone is trying to print something 995 * he shouldn't. 996 */ 997 if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && 998 (stb.st_dev != fdev || stb.st_ino != fino)) 999 return(ACCESS); 1000 |
999 job_dfcnt++; /* increment datafile counter for this job */ 1000 1001 /* everything seems OK, start it up */ | 1001 /* Everything seems OK for reading the file, now to send it */ 1002 filtcmd = NULL; |
1002 sizerr = 0; | 1003 sizerr = 0; |
1003 closedpr = 0; | 1004 tfd = -1; |
1004 if (type == '\3') { | 1005 if (type == '\3') { |
1005 if (pp->filters[LPF_INPUT]) { 1006 /* 1007 * We're sending something with an ifilter. We have to 1008 * run the ifilter and store the output as a temporary 1009 * spool file (tfile...), because the protocol requires 1010 * us to send the file size before we start sending any 1011 * of the data. 1012 */ 1013 char *av[15]; 1014 int n; 1015 int ifilter; 1016 union wait status; /* XXX */ | 1006 /* 1007 * Type == 3 means this is a datafile, not a control file. 1008 * Increment the counter of data-files in this job, and 1009 * then check for input or output filters (which are only 1010 * applied to datafiles, not control files). 1011 */ 1012 job_dfcnt++; |
1017 | 1013 |
1018 strcpy(tfile,TFILENAME); 1019 if ((tfd = mkstemp(tfile)) == -1) { 1020 syslog(LOG_ERR, "mkstemp: %m"); 1021 return(ERROR); 1022 } 1023 if ((av[0] = strrchr(pp->filters[LPF_INPUT], '/')) == NULL) 1024 av[0] = pp->filters[LPF_INPUT]; 1025 else 1026 av[0]++; | 1014 /* 1015 * Note that here we are filtering datafiles, one at a time, 1016 * as they are sent to the remote machine. Here, the *only* 1017 * difference between an input filter (`if=') and an output 1018 * filter (`of=') is the argument list that the filter is 1019 * started up with. Here, the output filter is executed 1020 * for each individual file as it is sent. This is not the 1021 * same as local print queues, where the output filter is 1022 * started up once, and then all jobs are passed thru that 1023 * single invocation of the output filter. 1024 * 1025 * Also note that a queue for a remote-machine can have an 1026 * input filter or an output filter, but not both. 1027 */ 1028 if (pp->filters[LPF_INPUT]) { 1029 filtcmd = pp->filters[LPF_INPUT]; 1030 av[0] = filtcmd; 1031 narg = 0; 1032 strcpy(opt_c, "-c"); 1033 strcpy(opt_h, "-h"); 1034 strcpy(opt_n, "-n"); |
1027 if (format == 'l') | 1035 if (format == 'l') |
1028 av[n=1] = "-c"; 1029 else 1030 n = 0; 1031 av[++n] = width; 1032 av[++n] = length; 1033 av[++n] = indent; 1034 av[++n] = "-n"; 1035 av[++n] = logname; 1036 av[++n] = "-h"; 1037 av[++n] = origin_host; 1038 av[++n] = pp->acct_file; 1039 av[++n] = 0; 1040 if ((ifilter = dofork(pp, DORETURN)) == 0) { /* child */ 1041 dup2(f, 0); 1042 dup2(tfd, 1); 1043 /* setup stderr for the filter (child process) 1044 * so it goes to our temporary errors file */ 1045 n = open(tempstderr, O_WRONLY|O_TRUNC, 0664); 1046 if (n >= 0) 1047 dup2(n, 2); 1048 closelog(); 1049 closeallfds(3); 1050 execv(pp->filters[LPF_INPUT], av); 1051 syslog(LOG_ERR, "cannot execv %s", 1052 pp->filters[LPF_INPUT]); 1053 exit(2); 1054 } 1055 (void) close(f); 1056 if (ifilter < 0) 1057 status.w_retcode = 100; 1058 else { 1059 while ((pid = wait((int *)&status)) > 0 && 1060 pid != ifilter) 1061 ; 1062 if (pid < 0) { 1063 status.w_retcode = 100; 1064 syslog(LOG_WARNING, "%s: after execv(%s), wait() returned: %m", 1065 pp->printer, pp->filters[LPF_INPUT]); 1066 } 1067 } 1068 /* Copy the filter's output to "lf" logfile */ 1069 if ((fp = fopen(tempstderr, "r"))) { 1070 while (fgets(buf, sizeof(buf), fp)) 1071 fputs(buf, stderr); 1072 fclose(fp); 1073 } 1074 /* process the return-code from the filter */ 1075 switch (status.w_retcode) { 1076 case 0: 1077 break; 1078 case 1: 1079 unlink(tfile); 1080 return(REPRINT); 1081 case 2: 1082 unlink(tfile); 1083 return(ERROR); 1084 default: 1085 syslog(LOG_WARNING, "%s: filter '%c' exited" 1086 " (retcode=%d)", 1087 pp->printer, format, status.w_retcode); 1088 unlink(tfile); 1089 return(FILTERERR); 1090 } 1091 statrc = fstat(tfd, &stb); /* to find size of tfile */ 1092 if (statrc < 0) { 1093 syslog(LOG_ERR, "%s: error processing 'if', fstat(%s): %m", 1094 pp->printer, tfile); 1095 return(ERROR); 1096 } 1097 f = tfd; 1098 lseek(f,0,SEEK_SET); 1099 } else if (ofilter) { 1100 /* 1101 * We're sending something with an ofilter, we have to 1102 * store the output as a temporary file (tfile)... the 1103 * protocol requires us to send the file size 1104 */ 1105 int i; 1106 for (i = 0; i < stb.st_size; i += BUFSIZ) { 1107 amt = BUFSIZ; 1108 if (i + amt > stb.st_size) 1109 amt = stb.st_size - i; 1110 if (sizerr == 0 && read(f, buf, amt) != amt) { 1111 sizerr = 1; 1112 break; 1113 } 1114 if (write(ofd, buf, amt) != amt) { 1115 (void) close(f); 1116 return(REPRINT); 1117 } 1118 } 1119 close(ofd); 1120 close(f); 1121 while ((i = wait(NULL)) > 0 && i != ofilter) 1122 ; 1123 if (i < 0) 1124 syslog(LOG_WARNING, "%s: after closing 'of', wait() returned: %m", 1125 pp->printer); 1126 ofilter = 0; 1127 statrc = fstat(tfd, &stb); /* to find size of tfile */ 1128 if (statrc < 0) { 1129 syslog(LOG_ERR, "%s: error processing 'of', fstat(%s): %m", 1130 pp->printer, tfile); 1131 openpr(pp); 1132 return(ERROR); 1133 } 1134 f = tfd; 1135 lseek(f,0,SEEK_SET); 1136 closedpr = 1; | 1036 av[++narg] = opt_c; 1037 av[++narg] = width; 1038 av[++narg] = length; 1039 av[++narg] = indent; 1040 av[++narg] = opt_n; 1041 av[++narg] = logname; 1042 av[++narg] = opt_h; 1043 av[++narg] = origin_host; 1044 av[++narg] = pp->acct_file; 1045 av[++narg] = NULL; 1046 } else if (pp->filters[LPF_OUTPUT]) { 1047 filtcmd = pp->filters[LPF_OUTPUT]; 1048 av[0] = filtcmd; 1049 narg = 0; 1050 av[++narg] = width; 1051 av[++narg] = length; 1052 av[++narg] = NULL; |
1137 } 1138 } | 1053 } 1054 } |
1055 if (filtcmd) { 1056 /* 1057 * If there is an input or output filter, we have to run 1058 * the datafile thru that filter and store the result as 1059 * a temporary spool file, because the protocol requires 1060 * that we send the remote host the file-size before we 1061 * start to send any of the data. 1062 */ 1063 strcpy(tfile, TFILENAME); 1064 tfd = mkstemp(tfile); 1065 if (tfd == -1) { 1066 syslog(LOG_ERR, "%s: mkstemp(%s): %m", pp->printer, 1067 TFILENAME); 1068 return (ERROR); 1069 } 1070 filtstat = execfilter(pp, filtcmd, av, f, tfd); |
|
1139 | 1071 |
1072 /* process the return-code from the filter */ 1073 switch (filtstat) { 1074 case 0: 1075 break; 1076 case 1: 1077 unlink(tfile); 1078 return (REPRINT); 1079 case 2: 1080 unlink(tfile); 1081 return (ERROR); 1082 default: 1083 syslog(LOG_WARNING, 1084 "%s: filter '%c' exited (retcode=%d)", 1085 pp->printer, format, filtstat); 1086 unlink(tfile); 1087 return (FILTERERR); 1088 } 1089 statrc = fstat(tfd, &stb); /* to find size of tfile */ 1090 if (statrc < 0) { 1091 syslog(LOG_ERR, 1092 "%s: error processing 'if', fstat(%s): %m", 1093 pp->printer, tfile); 1094 return (ERROR); 1095 } 1096 f = tfd; 1097 lseek(f,0,SEEK_SET); 1098 } 1099 |
|
1140 (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file); 1141 amt = strlen(buf); 1142 for (i = 0; ; i++) { 1143 if (write(pfd, buf, amt) != amt || 1144 (resp = response(pp)) < 0 || resp == '\1') { 1145 (void) close(f); 1146 if (tfd != -1 && type == '\3') { 1147 tfd = -1; 1148 unlink(tfile); | 1100 (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file); 1101 amt = strlen(buf); 1102 for (i = 0; ; i++) { 1103 if (write(pfd, buf, amt) != amt || 1104 (resp = response(pp)) < 0 || resp == '\1') { 1105 (void) close(f); 1106 if (tfd != -1 && type == '\3') { 1107 tfd = -1; 1108 unlink(tfile); |
1149 if (closedpr) 1150 openpr(pp); | |
1151 } 1152 return(REPRINT); 1153 } else if (resp == '\0') 1154 break; 1155 if (i == 0) 1156 pstatus(pp, 1157 "no space on remote; waiting for queue to drain"); 1158 if (i == 10) --- 11 unchanged lines hidden (view full) --- 1170 amt = stb.st_size - i; 1171 if (sizerr == 0 && read(f, buf, amt) != amt) 1172 sizerr = 1; 1173 if (write(pfd, buf, amt) != amt) { 1174 (void) close(f); 1175 if (tfd != -1 && type == '\3') { 1176 tfd = -1; 1177 unlink(tfile); | 1109 } 1110 return(REPRINT); 1111 } else if (resp == '\0') 1112 break; 1113 if (i == 0) 1114 pstatus(pp, 1115 "no space on remote; waiting for queue to drain"); 1116 if (i == 10) --- 11 unchanged lines hidden (view full) --- 1128 amt = stb.st_size - i; 1129 if (sizerr == 0 && read(f, buf, amt) != amt) 1130 sizerr = 1; 1131 if (write(pfd, buf, amt) != amt) { 1132 (void) close(f); 1133 if (tfd != -1 && type == '\3') { 1134 tfd = -1; 1135 unlink(tfile); |
1178 if (closedpr) 1179 openpr(pp); | |
1180 } 1181 return(REPRINT); 1182 } 1183 } 1184 1185 (void) close(f); 1186 if (tfd != -1 && type == '\3') { 1187 tfd = -1; 1188 unlink(tfile); 1189 } 1190 if (sizerr) { 1191 syslog(LOG_INFO, "%s: %s: changed size", pp->printer, file); 1192 /* tell recvjob to ignore this file */ 1193 (void) write(pfd, "\1", 1); | 1136 } 1137 return(REPRINT); 1138 } 1139 } 1140 1141 (void) close(f); 1142 if (tfd != -1 && type == '\3') { 1143 tfd = -1; 1144 unlink(tfile); 1145 } 1146 if (sizerr) { 1147 syslog(LOG_INFO, "%s: %s: changed size", pp->printer, file); 1148 /* tell recvjob to ignore this file */ 1149 (void) write(pfd, "\1", 1); |
1194 if (closedpr) 1195 openpr(pp); | |
1196 return(ERROR); 1197 } 1198 if (write(pfd, "", 1) != 1 || response(pp)) { | 1150 return(ERROR); 1151 } 1152 if (write(pfd, "", 1) != 1 || response(pp)) { |
1199 if (closedpr) 1200 openpr(pp); | |
1201 return(REPRINT); 1202 } | 1153 return(REPRINT); 1154 } |
1203 if (closedpr) 1204 openpr(pp); | |
1205 if (type == '\3') 1206 trstat_write(pp, TR_SENDING, stb.st_size, logname, 1207 pp->remote_host, origin_host); 1208 return(OK); 1209} 1210 1211/* | 1155 if (type == '\3') 1156 trstat_write(pp, TR_SENDING, stb.st_size, logname, 1157 pp->remote_host, origin_host); 1158 return(OK); 1159} 1160 1161/* |
1162 * This routine is called to execute one of the filters as was 1163 * specified in a printcap entry. 1164 */ 1165static int 1166execfilter(struct printer *pp, char *f_cmd, char *f_av[], int infd, int outfd) 1167{ 1168 int errfd, fpid, wpid; 1169 FILE *errfp; 1170 union wait status; /* XXX */ 1171 char buf[BUFSIZ], *slash; 1172 1173 fpid = dofork(pp, DORETURN); 1174 if (fpid != 0) { 1175 /* 1176 * This is the parent process, which just waits for the child 1177 * to complete and then returns the result. Note that it is 1178 * the child process which reads the input stream. 1179 */ 1180 (void) close(infd); 1181 if (fpid < 0) 1182 status.w_retcode = 100; 1183 else { 1184 while ((wpid = wait((int *)&status)) > 0 && 1185 wpid != fpid) 1186 ; 1187 if (wpid < 0) { 1188 status.w_retcode = 100; 1189 syslog(LOG_WARNING, 1190 "%s: after execv(%s), wait() returned: %m", 1191 pp->printer, f_cmd); 1192 } 1193 } 1194 1195 /* 1196 * Copy everything the filter wrote to stderr from our 1197 * temporary errors file to the "lf=" logfile. 1198 */ 1199 errfp = fopen(tempstderr, "r"); 1200 if (errfp) { 1201 while (fgets(buf, sizeof(buf), errfp)) 1202 fputs(buf, stderr); 1203 fclose(errfp); 1204 } 1205 1206 return (status.w_retcode); 1207 } 1208 1209 /* 1210 * This is the child process, which is the one that executes the 1211 * given filter. 1212 */ 1213 /* 1214 * If the first parameter has any slashes in it, then change it 1215 * to point to the first character after the last slash. 1216 */ 1217 slash = strrchr(f_av[0], '/'); 1218 if (slash != NULL) 1219 f_av[0] = slash + 1; 1220 /* 1221 * XXX - in the future, this should setup an explicit list of 1222 * environment variables and use execve()! 1223 */ 1224 1225 /* 1226 * Setup stdin, stdout, and stderr as we want them when the filter 1227 * is running. Stderr is setup so it points to a temporary errors 1228 * file, and the parent process will copy that temporary file to 1229 * the real logfile after the filter completes. 1230 */ 1231 dup2(infd, 0); 1232 dup2(outfd, 1); 1233 errfd = open(tempstderr, O_WRONLY|O_TRUNC, 0664); 1234 if (errfd >= 0) 1235 dup2(errfd, 2); 1236 closelog(); 1237 closeallfds(3); 1238 execv(f_cmd, f_av); 1239 syslog(LOG_ERR, "%s: cannot execv %s", pp->printer, f_cmd); 1240 exit(2); 1241 /* NOTREACHED */ 1242} 1243 1244/* |
|
1212 * Check to make sure there have been no errors and that both programs 1213 * are in sync with eachother. 1214 * Return non-zero if the connection was lost. 1215 */ 1216static char 1217response(const struct printer *pp) 1218{ 1219 char resp; --- 334 unchanged lines hidden (view full) --- 1554static void 1555openpr(const struct printer *pp) 1556{ 1557 int p[2]; 1558 char *cp; 1559 1560 if (pp->remote) { 1561 openrem(pp); | 1245 * Check to make sure there have been no errors and that both programs 1246 * are in sync with eachother. 1247 * Return non-zero if the connection was lost. 1248 */ 1249static char 1250response(const struct printer *pp) 1251{ 1252 char resp; --- 334 unchanged lines hidden (view full) --- 1587static void 1588openpr(const struct printer *pp) 1589{ 1590 int p[2]; 1591 char *cp; 1592 1593 if (pp->remote) { 1594 openrem(pp); |
1595 /* 1596 * Lpd does support the setting of 'of=' filters for 1597 * jobs going to remote machines, but that does not 1598 * have the same meaning as 'of=' does when handling 1599 * local print queues. For remote machines, all 'of=' 1600 * filter processing is handled in sendfile(), and that 1601 * does not use these global "output filter" variables. 1602 */ 1603 ofd = -1; 1604 ofilter = 0; 1605 return; |
|
1562 } else if (*pp->lp) { 1563 if ((cp = strchr(pp->lp, '@')) != NULL) 1564 opennet(pp); 1565 else 1566 opentty(pp); 1567 } else { 1568 syslog(LOG_ERR, "%s: no line printer device or host name", 1569 pp->printer); --- 236 unchanged lines hidden --- | 1606 } else if (*pp->lp) { 1607 if ((cp = strchr(pp->lp, '@')) != NULL) 1608 opennet(pp); 1609 else 1610 opentty(pp); 1611 } else { 1612 syslog(LOG_ERR, "%s: no line printer device or host name", 1613 pp->printer); --- 236 unchanged lines hidden --- |