cdesktopenv/cde/programs/dtprintinfo/objects/PrintObj/ParseJobs.C

1403 lines
35 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: ParseJobs.C /main/12 1998/08/03 16:30:29 mgreess $ */
/* *
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
* (c) Copyright 1993, 1994 International Business Machines Corp. *
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
* (c) Copyright 1993, 1994 Novell, Inc. *
*/
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#if defined(_AIX)
/*
* XXXXX - AIX hack alert!!! This is needed for an AIX defect
* in the definition of inet_addr in <arpa/inet.h>
*/
extern "C" in_addr_t inet_addr(const char *);
#endif
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <time.h>
#include <stdlib.h>
#include <ctype.h>
#include <X11/Intrinsic.h>
#include "dtprintinfomsg.h"
#ifdef NO_REGCOMP
#include <ctype.h>
#if defined(SVR4) || defined(SYSV)
#include <libgen.h>
#endif
#else
#include <regex.h>
#endif
#if defined(aix)
extern "C" { int rresvport(int *); }
#endif
#ifdef hpux
#define SETEUID(id) setresuid(getuid(), (uid_t)id, (uid_t)0);
#else
#if defined(aix)
extern "C" { extern int seteuid(uid_t); }
#endif
#define SETEUID(id) seteuid((uid_t)id)
#endif
#include "ParseJobs.h"
#include "Invoke.h"
static int G_AIX_LOCAL = 0;
int RemotePrintJobs(char *server, char *printer, char **job_list, int *n_jobs)
{
*n_jobs = 0;
*job_list = NULL;
// hookup to Server
int sockfd;
if ((sockfd = ConnectToPrintServer(server, 15)) == -1)
return 0;
char *output = NULL;
int rc = 0;
if (SendPrintJobStatusReguest(sockfd, printer))
{
int len = 512;
int ctr = 1;
int n;
output = (char *)malloc(512);
char *out1 = output;
char *out2 = out1 + 511;
while (1)
{
if ((n = read(sockfd, out1, len)) == len)
{
len = 512;
ctr++;
output = (char *)realloc(output, (ctr * 512));
out1 = output + ((ctr - 1) * 512);
out2 = out1 + 511;
}
else if (n > 0)
{
out1 += n;
len = out2 - out1 + 1;
}
else
break;
}
*out1 = 0;
close(sockfd);
rc = 1;
}
if (output)
{
if (*output)
rc = ParseRemotePrintJobs(printer, output, job_list, n_jobs);
free(output);
}
return rc;
}
int ParseRemotePrintJobs(char *printer, char *jobs, char **job_list,
int *n_jobs)
{
*n_jobs = 0;
*job_list = NULL;
int rc = 0;
if (jobs && *jobs)
{
switch (DetermineOutput(jobs))
{
case AIX_V2_OUTPUT:
rc = ParseAIXv2PrintJobs(printer, jobs, job_list, n_jobs);
break;
case AIX_V3_OUTPUT:
rc = ParseAIXv3PrintJobs(printer, jobs, job_list, n_jobs);
break;
case BSD_OUTPUT:
rc = ParseBSDPrintJobs(printer, jobs, job_list, n_jobs);
break;
default:
case UNKNOWN_OUTPUT:
rc = 1;
break;
}
}
return rc;
}
static void connect_timeout(int not_used)
{
not_used = 0;
}
// Create a connection to the remote printer server.
int ConnectToPrintServer(const char *rhost, int timeout)
{
struct hostent *hp;
struct servent *sp;
struct sockaddr_in sin;
int s, lport = IPPORT_RESERVED - 1;
// Get the host address and port number to connect to.
if (!(hp = gethostbyname(rhost)))
{
unsigned long tmpaddr = inet_addr(rhost);
hp = gethostbyaddr((char *)&tmpaddr, sizeof(tmpaddr), AF_INET);
}
if (hp == NULL)
return -1;
if (!(sp = getservbyname("printer", "tcp")))
return -1;
memset((char *)&sin, 0, sizeof(sin));
memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
sin.sin_family = hp->h_addrtype;
sin.sin_port = sp->s_port;
// run as user's UID, but with privileges from root
SETEUID(0);
// Try connecting to the server.
s = rresvport(&lport);
signal(SIGALRM, connect_timeout);
if (timeout > 0)
alarm(timeout);
else
alarm(15);
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
close(s);
s = -1;
}
alarm(0);
SETEUID(getuid());
return s;
}
int SendPrintJobStatusReguest(int sockfd, const char *printer)
{
char *buf = new char[100];
int size;
sprintf(buf, "%c%s \n", '\4', printer);
size=strlen(buf);
size = write(sockfd, buf, size);
if (write(sockfd, buf, size) != size)
{
close(sockfd);
delete [] buf;
return 0;
}
delete [] buf;
return 1;
}
JobOutputType DetermineOutput(char *output)
{
char *s, *s1;
int i;
static int first_time = 1;
#ifdef NO_REGCOMP
static char *aixv2_pattern;
static char *aixv3_pattern;
static char *bsd_pattern;
/*
* Due to bug in regcmp/regex (bug id 1191772), change to C locale for
* this parsing work. And change back at end of procedure. This workaround
* appears to be ok since the print service output parsed here is in a
* "C locale" 8-bit form for inter-machine networking.
*/
setlocale(LC_ALL, "C");
if (first_time)
{
aixv2_pattern = regcmp("dev.*arg.*status.*request", (char *)NULL);
aixv3_pattern = regcmp("Queue.*Dev.*Status.*Job", (char *)NULL);
bsd_pattern = regcmp(":.*\\[.*\\]", (char *)NULL);
first_time = 0;
}
#else
static regex_t aixv2_pattern;
static regex_t aixv3_pattern;
static regex_t bsd_pattern;
if (first_time)
{
regcomp(&aixv2_pattern, "dev.*arg.*status.*request", REG_NOSUB);
regcomp(&aixv3_pattern, "Queue.*Dev.*Status.*Job", REG_NOSUB);
regcomp(&bsd_pattern, ":.*\\[.*\\]", REG_NOSUB);
first_time = 0;
}
#endif
s = output;
if (s1 = strchr(s, '\n'))
s1++;
i = 0;
while (i < 10 && s && *s)
{
#ifdef NO_REGCOMP
if (regex(bsd_pattern, s)) {
setlocale(LC_ALL, "");
return BSD_OUTPUT;
}
if (regex(aixv3_pattern, s)) {
setlocale(LC_ALL, "");
return AIX_V3_OUTPUT;
}
if (regex(aixv2_pattern, s)) {
setlocale(LC_ALL, "");
return AIX_V2_OUTPUT;
}
#else
if (!regexec(&bsd_pattern, s, (size_t)0, NULL, 0))
return BSD_OUTPUT;
if (!regexec(&aixv3_pattern, s, (size_t)0, NULL, 0))
return AIX_V3_OUTPUT;
if (!regexec(&aixv2_pattern, s, (size_t)0, NULL, 0))
return AIX_V2_OUTPUT;
#endif
s = s1;
if (s1 = strchr(s, '\n'))
s1++;
i++;
}
#ifdef NO_REGCOMP
setlocale(LC_ALL, "");
#endif
return UNKNOWN_OUTPUT;
}
///////////////////////////// LOCAL PARSERS /////////////////////////////////
#ifdef aix
void LocalPrintJobs(char *printer, char **job_list, int *n_jobs)
{
char *output;
char *cmd = new char[60];
sprintf(cmd, "LANG=C enq -LP%s", printer);
Invoke *_thread = new Invoke(cmd, &output);
// run as user's UID, but with privileges from root
SETEUID(0);
G_AIX_LOCAL = 1;
ParseAIXv3PrintJobs(printer, output, job_list, n_jobs);
G_AIX_LOCAL = 0;
SETEUID(getuid());
delete [] cmd;
delete output;
delete _thread;
}
#endif
#if defined(sun)
// SUN LOCAL PARSER, actually this gets the local information from the file
// system, it should have the good performance since no processes (lpstat)
// are needed.
typedef struct
{
int immediate;
long secs;
char *line;
} StatusLineStruct, *StatusLine, **StatusLineList;
#define TMP_DIR "/var/spool/lp/tmp"
#define REQ_DIR "/var/spool/lp/requests/%s/"
#define SPOOL_DIR "/var/spool/lp/tmp/%s/"
static void check_dir(char *printer, char *tmp_dir, StatusLineList *job_list,
int *n_jobs, int prev_n_jobs);
static int SortJobs(const void *, const void *);
void LocalPrintJobs(char *printer, char **return_job_list, int *return_n_jobs)
{
DIR *lp_tmp_dir;
struct dirent *dir_struct;
struct stat statbuff;
int n_jobs = 0;
int i;
char oldpwd[300];
int current_size;
int len;
static char *job_list1 = NULL;
static int prev_buf_size = 0;
static StatusLineList job_list = NULL;
static int prev_n_jobs = 0;
if (prev_buf_size == 0)
{
prev_buf_size = BUFSIZ;
job_list1 = (char *)malloc(prev_buf_size);
}
current_size = 0;
*job_list1 = '\0';
*return_n_jobs = 0;
// run as user's UID, but with privileges from root
SETEUID(0);
getcwd(oldpwd, 300);
if (getenv("TMP_DIR"))
chdir(getenv("TMP_DIR"));
else
chdir(TMP_DIR);
if (!(lp_tmp_dir = opendir(".")))
{
*return_job_list = NULL;
*return_n_jobs = 0;
chdir(oldpwd);
SETEUID(getuid());
return;
}
dir_struct = readdir(lp_tmp_dir);
for ( ; dir_struct ; dir_struct = readdir(lp_tmp_dir))
{
if (*dir_struct->d_name == '.')
continue;
if (stat(dir_struct->d_name, &statbuff) >= 0 &&
statbuff.st_mode & S_IFDIR)
{
chdir(dir_struct->d_name);
check_dir(printer, dir_struct->d_name, &job_list, &n_jobs,
prev_n_jobs);
chdir("..");
}
}
closedir(lp_tmp_dir);
prev_n_jobs = prev_n_jobs > n_jobs ? prev_n_jobs : n_jobs;
qsort(job_list, n_jobs, sizeof(StatusLineList), SortJobs);
for (i = 0; i < n_jobs; i++)
{
len = strlen(job_list[i]->line);
if (prev_buf_size < (current_size + len + 1))
job_list1 = (char *) realloc(job_list1, (current_size + len + 1) *
sizeof(char *));
memcpy(job_list1 + current_size, job_list[i]->line, len);
current_size += len;
}
*(job_list1 + current_size) = '\0';
prev_buf_size = prev_buf_size > current_size ? prev_buf_size : current_size;
*return_job_list = job_list1;
*return_n_jobs = n_jobs;
chdir(oldpwd);
SETEUID(getuid());
}
static void check_dir(char *printer, char *tmp_dir, StatusLineList *job_list,
int *n_jobs, int prev_n_jobs)
{
DIR *lp_tmp_dir;
struct dirent *dir_struct;
char buf[256];
int req_len;
int spool_len;
int line_ct;
char *line;
char date_str[100];
char owner[100];
char job_size[100];
FILE *req, *job;
time_t secs;
int found;
int immediate;
char *s;
char title[200];
char *jobname;
StatusLineList j_list;
char *filename = new char[200];
char *filename1 = new char[200];
char *request = new char[300];
char *spool_dir = new char[300];
if (getenv("REQ_DIR"))
sprintf(request, getenv("REQ_DIR"), tmp_dir);
else
sprintf(request, REQ_DIR, tmp_dir);
req_len = strlen(request);
sprintf(spool_dir, SPOOL_DIR, tmp_dir);
spool_len = strlen(spool_dir);
if (!(lp_tmp_dir = opendir(".")))
{
delete [] filename;
delete [] filename1;
delete [] request;
delete [] spool_dir;
return;
}
dir_struct = readdir(lp_tmp_dir);
for ( ; dir_struct ; dir_struct = readdir(lp_tmp_dir))
{
int len = strlen(dir_struct->d_name);
if (len < 3)
continue;
if (strcmp(dir_struct->d_name + len - 2, "-0"))
continue;
*(request + req_len) = '\0';
strcat(request + req_len, dir_struct->d_name);
if (!(req = fopen(request, "r")))
continue;
if (!(job = fopen(dir_struct->d_name, "r")))
{
fclose(req);
continue;
}
found = 1;
immediate = 0;
title[0] = '\0';
filename[0] = '\0';
filename1[0] = '\0';
date_str[0] = '\0';
owner[0] = '\0';
job_size[0] = '\0';
while (found && fgets(buf, 100, job))
{
line = strtok(buf, "\n");
switch (*line)
{
case 'H':
if (!strcmp("immediate", line + 2))
immediate = 1;
break;
case 'D':
if (strcmp(printer, line + 2))
found = 0;
break;
case 'F':
*(spool_dir + spool_len) = '\0';
strncat(spool_dir, dir_struct->d_name, len - 1);
strcat(spool_dir, "1");
if (strcmp(spool_dir, line + 2))
strcpy(filename1, line + 2);
else
*filename1 = '\0';
break;
case 'O':
if (s = strrchr(line, ':'))
*s = '\0';
if (s = strrchr(line, '\''))
{
s++;
for ( ; *s == ' '; s++)
;
}
strcpy(filename, s);
if (*s == '\0')
{
if (s = strstr(line, "-T"))
{
int i = 0;
s += 2;
while (1)
{
if (*s == ' ')
{
if (i == 0)
{
i++;
break;
}
else
{
i--;
if (filename[i] != '\\')
{
i++;
break;
}
}
}
filename[i++] = *s;
s++;
}
filename[i] = '\0';
}
}
break;
case 'T':
if (s = strstr(line, "\\n"))
*s = '\0';
strcpy(title, line + 2);
break;
}
}
if (found)
{
line_ct = 1;
while (line_ct)
{
fgets(buf, 100, req);
line = strtok(buf, "\n");
switch (line_ct)
{
case 3:
if (s = strchr(line, '!'))
{
*s = '\0';
s++;
strcpy(owner, s);
strcat(owner, "@");
strcat(owner, line);
if (s = strchr(owner, '.'))
*s = '\0';
}
else
strcpy(owner, line);
break;
case 5: strcpy(job_size, line); break;
case 6:
secs = (time_t)atoi(line);
strftime(date_str, 100, "%b %e|%T", localtime(&secs));
line_ct = -1;
break;
}
line_ct++;
}
if (s = strstr(dir_struct->d_name, "-0"))
*s = '\0';
if (*filename)
jobname = filename;
else if (*filename1)
jobname = filename1;
else if (*title)
jobname = title;
else
{
sprintf(filename, "%s-%s", printer, dir_struct->d_name);
jobname = filename;
}
if (*n_jobs >= prev_n_jobs)
{
if (*n_jobs == 0)
*job_list = (StatusLineList) malloc(sizeof(StatusLine));
else
*job_list = (StatusLineList) realloc(*job_list, (*n_jobs + 1) *
sizeof(StatusLine));
j_list = *job_list;
j_list[*n_jobs] = (StatusLine) malloc(sizeof(StatusLineStruct));
len = 7 + strlen(printer) + strlen(jobname) + strlen(date_str) +
strlen(dir_struct->d_name) + strlen(owner) + strlen(job_size);
j_list[*n_jobs]->line = (char *) malloc(len);
}
else
{
j_list = *job_list;
len = 7 + strlen(printer) + strlen(jobname) + strlen(date_str) +
strlen(dir_struct->d_name) + strlen(owner) + strlen(job_size);
j_list[*n_jobs]->line = (char *)realloc(j_list[*n_jobs]->line, len);
}
sprintf(j_list[*n_jobs]->line, "%s|%s|%s|%s|%s|%s\n", printer,
jobname, dir_struct->d_name, owner, date_str, job_size);
j_list[*n_jobs]->secs = (long) secs;
j_list[*n_jobs]->immediate = immediate;
(*n_jobs)++;
}
fclose(req);
fclose(job);
}
closedir(lp_tmp_dir);
delete [] filename;
delete [] filename1;
delete [] request;
delete [] spool_dir;
}
static int SortJobs(const void *_first, const void *_second)
{
StatusLineList first = (StatusLineList)_first;
StatusLineList second = (StatusLineList)_second;
if ((**first).immediate && !(**second).immediate)
return -1;
if (!(**first).immediate && (**second).immediate)
return 1;
if ((**first).immediate)
return (int)((**second).secs - (**first).secs);
else
return (int)((**first).secs - (**second).secs);
}
#endif // SUN LOCAL PARSER
#ifdef hpux
/* HP LOCAL PARSER - have to parse the following
Need to parse the following 2 forms of output:
coseps-28 guest priority 0 Aug 9 12:54 on coseps
test.ps 31160 bytes
OR
coseps-29 guest priority 0 Aug 9 12:56 on hostname
(standard input) 31160 bytes
*/
void LocalPrintJobs(char *printer, char **return_job_list, int *return_n_jobs)
{
char *buf = new char[300];
char *s, *s1, *c;
char *qname;
char *jname;
char *jnumber;
char *owner;
char *month;
char *day;
char *stime;
char *jsize;
char *hostname;
int current_size;
int len;
char *output;
static char *job_list = NULL;
static int prev_buf_size = 0;
sprintf(buf, "LANG=C lpstat -i -o%s", printer);
Invoke *_thread = new Invoke(buf, &output);
if (prev_buf_size == 0)
{
prev_buf_size = BUFSIZ;
job_list = (char *)malloc(prev_buf_size);
}
current_size = 0;
*job_list = '\0';
*return_n_jobs = 0;
s = output;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
while (s && *s)
{
qname = strtok(s, "-");
jnumber = strtok(NULL, " ");
owner = strtok(NULL, " ");
strtok(NULL, " ");
strtok(NULL, " ");
month = strtok(NULL, " ");
day = strtok(NULL, " ");
stime = strtok(NULL, " \n");
strtok(NULL, " ");
hostname = strtok(NULL, " \n");
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
for (jname = s; *jname == '\t' || *jname == ' '; jname++)
;
jsize = strrchr(s, ' ');
*jsize = '\0';
jsize = strrchr(s, ' ') + 1;
for (c = jsize - 1; *c == ' '; c--)
;
*(c + 1) = '\0';
if (hostname && strcmp(qname, hostname))
sprintf(buf, "%s|%s|%s|%s@%s|%s %s|%s|%s\n", qname, jname, jnumber,
owner, hostname, month, day, stime, jsize);
else
sprintf(buf, "%s|%s|%s|%s|%s %s|%s|%s\n", qname, jname, jnumber,
owner, month, day, stime, jsize);
len = strlen(buf);
if (prev_buf_size < (current_size + len + 1))
job_list = (char *) realloc(job_list, (current_size + len + 1) *
sizeof(char *));
memcpy(job_list + current_size, buf, len);
current_size += len;
(*return_n_jobs)++;
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
}
*(job_list + current_size) = '\0';
prev_buf_size = prev_buf_size > current_size ? prev_buf_size : current_size;
*return_job_list = job_list;
delete [] buf;
delete output;
delete _thread;
}
#endif // HP LOCAL PARSER
#if defined(__linux__) || defined(CSRG_BASED)
//Linux local parser
#define NEXT_OUTPUT_LINE(line,rest) \
do \
{ \
line = rest; \
if (line && (rest = strchr(line, '\n'))) \
*rest++ = '\0'; \
} while (NULL != line && 0 == *line);
void LocalPrintJobs(char *printer, char **return_job_list, int *return_n_jobs)
{
char *buf = new char[1000];
char *s, *s1, *c;
char *qname = NULL;
char *jname;
char *jnumber;
char *owner;
char *month;
char *day;
char *date;
char *year;
char *network;
char *output;
char *stime;
char *jsize;
char *hostname;
int current_size;
int len;
int has_pri = 0;
static char *job_list = NULL;
static int prev_buf_size = 0;
#if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__)
snprintf(buf, 1000, "LANG=C lpq -P%s", printer);
#elif defined(__FreeBSD__)
snprintf(buf, 1000, "LANG=C /usr/local/bin/lpq -P%s", printer);
#endif
Invoke *_thread = new Invoke(buf, &output);
if (prev_buf_size == 0)
{
prev_buf_size = BUFSIZ;
job_list = (char*) malloc(prev_buf_size);
}
current_size = 0;
*job_list = '\0';
*return_n_jobs = 0;
s1 = output;
NEXT_OUTPUT_LINE(s,s1);
//
// Parse the optional "Requests on" line of output to verify printer name.
// "Requests on ansel:"
//
{
char *opt_requests_on_line = "Requests on ";
if (0 == strncmp(s, opt_requests_on_line, strlen(opt_requests_on_line)))
{
char *requests = strtok(s, " ");
char *on = strtok(NULL, " ");
qname = strtok(NULL, " :\n");
if (0 != strncmp(qname, printer, strlen(qname)))
fprintf(
stderr,
"Found the wrong printer: looking for '%s'; found '%s'\n",
printer, qname);
NEXT_OUTPUT_LINE(s,s1);
}
}
//
// Parse the host/date line of output to collect host, date, and time.
// "Fri Oct 4 09:08:48 1996: "
//
{
hostname = strtok(s, ":");
day = strtok(NULL, " ");
month = strtok(NULL, " ");
date = strtok(NULL, " ");
stime = strtok(NULL, " ");
year = strtok(NULL, " \n");
}
NEXT_OUTPUT_LINE(s,s1);
//
// If this is the "no entries" line, we're done. Return.
// "no entries"
//
{
char *no_entries_line = "no entries";
if (0 == strncmp(s, no_entries_line, strlen(no_entries_line)))
{
*return_job_list = job_list;
free(output);
return;
}
}
//
// Parse the optional printer status line.
// "federal is ready and printing via dev"
//
{
char *buffer = new char[128];
char *opt_status_line = buffer;
sprintf(buffer, "%s is ready and printing via ", printer);
if (0 == strncmp(s, opt_status_line, strlen(opt_status_line)))
{
qname = strtok(s, " \t");
strtok(NULL, " ");
strtok(NULL, " ");
strtok(NULL, " ");
strtok(NULL, " ");
strtok(NULL, " ");
network = strtok(s, " \n");
NEXT_OUTPUT_LINE(s,s1);
}
delete [] buffer;
}
//
// Parse the legend line.
// "Rank Owner Job Files Total Size"
// or
// "Rank Pri Owner Job Files Total Size"
//
{
char *tmp;
tmp = strtok(s, " ");
if (strcmp(tmp, "Rank"))
fprintf(stderr, "Unexpected legend column: %s != Rank\n", tmp);
tmp = strtok(NULL, " ");
if (0 == strcmp(tmp, "Pri"))
{
has_pri = TRUE;
tmp = strtok(NULL, " ");
}
if (strcmp(tmp, "Owner"))
fprintf(stderr, "Unexpected legend column: %s != Owner\n", tmp);
tmp = strtok(NULL, " ");
if (strcmp(tmp, "Job"))
fprintf(stderr, "Unexpected legend column: %s != Job\n", tmp);
tmp = strtok(NULL, " ");
if (strcmp(tmp, "Files"))
fprintf(stderr, "Unexpected legend column: %s != Files\n", tmp);
tmp = strtok(NULL, " ");
if (strcmp(tmp, "Total"))
fprintf(stderr, "Unexpected legend column: %s != Total\n", tmp);
tmp = strtok(NULL, " \n");
if (strcmp(tmp, "Size"))
fprintf(stderr, "Unexpected legend column: %s != Size\n", tmp);
}
NEXT_OUTPUT_LINE(s,s1);
//
// Parse the job lines.
// "active mgreess 65 (standard input) 13482 bytes"
// or
// "1st 0 mgreess 7 ParseJobs.C 33367 bytes"
//
while (s && *s)
{
strtok(s, " \t");
if (has_pri)
strtok(NULL, " ");
owner = strtok(NULL, " ");
jnumber = strtok(NULL, " ");
jname = strtok(NULL," ");
jsize = strtok(NULL," ");
if (NULL == owner || NULL == jnumber || NULL == jname || NULL == jsize)
{
NEXT_OUTPUT_LINE(s,s1);
continue;
}
if (NULL == qname)
qname = printer;
if (hostname && strcmp(qname, hostname))
sprintf(buf, "%s|%s|%s|%s@%s|%s %s|%s|%s\n", qname, jname, jnumber,
owner, hostname, month, date, stime, jsize);
else
sprintf(buf, "%s|%s|%s|%s|%s %s|%s|%s\n", qname, jname, jnumber,
owner, month, date, stime, jsize);
printf("qname, jname, jnumber, owner, ");
printf("hostname, month, date, stime, jsize\n");
printf("%s\n", buf);
len = strlen(buf);
if (prev_buf_size < (current_size + len + 1))
job_list =
(char*) realloc(job_list, (current_size + len + 1) * sizeof(char*));
memcpy(job_list + current_size, buf, len);
current_size += len;
(*return_n_jobs)++;
NEXT_OUTPUT_LINE(s,s1);
}
*(job_list + current_size) = '\0';
prev_buf_size = prev_buf_size > current_size ? prev_buf_size : current_size;
*return_job_list = job_list;
free(output);
delete [] buf;
}
#endif // Linux local parser
/* BSD PARSER - have to parse the following
BSD, HP, and SUN output
Warning: test1 is down: b906ps3 is ready and printing
Warning: no daemon present
root: 1st [job 006b906ps3.austin.ibm.com]
/etc/motd 421 bytes
root: 2nd [job 006b906ps3.austin.ibm.com]
<File name not available> 421 bytes
*/
int ParseBSDPrintJobs(char *printer, char *jobs,
char **return_job_list, int *return_n_jobs)
{
char *s, *s1;
char *jname;
char jnumber[9];
char *owner;
char *sdate;
char *stime;
char *jsize;
char *hostname;
int current_size;
int len;
char *buf = new char[300];
static char *job_list = NULL;
static int prev_buf_size = 0;
static int first_time = 1;
int rc = 1;
#ifdef NO_REGCOMP
static char *bsd_pattern;
/*
* Due to bug in regcmp/regex (bug id 1191772), change to C locale for
* this parsing work. And change back at end of procedure. This workaround
* appears to be ok since the print service output parsed here is in a
* "C locale" 8-bit form for inter-machine networking.
*/
setlocale(LC_ALL, "C");
if (first_time)
{
bsd_pattern = regcmp(":.*\\[.*\\]", (char *)NULL);
first_time = 0;
}
#else
static regex_t bsd_pattern;
if (first_time)
{
regcomp(&bsd_pattern, ":.*\\[.*\\]", REG_NOSUB);
first_time = 0;
}
#endif
if (prev_buf_size == 0)
{
prev_buf_size = BUFSIZ;
job_list = (char *)malloc(prev_buf_size);
}
current_size = 0;
*job_list = '\0';
*return_n_jobs = 0;
sdate = MESSAGE(NotAvailableL);
stime = sdate;
s = strtok(jobs, "\n");
while (s)
{
#ifdef NO_REGCOMP
if (regex(bsd_pattern, s))
#else
if (!regexec(&bsd_pattern, s, (size_t)0, NULL, 0))
#endif
{
owner = s;
s = strchr(s, ':');
*s++ = '\0';
s = strchr(s, '[');
s1 = jnumber;
for (s = strchr(s, ' ') + 1; isdigit((int)*s); s++)
*s1++ = *s;
*s1++ = '\0';
for (s1 = s; *s1 == ' '; s1++)
;
hostname = s1;
if (s = strchr(hostname, '.'))
*s = '\0';
else
*(strchr(hostname, ']')) = '\0';
s = strtok(NULL, "\n");
for (s1 = s; *s1 == ' ' || *s1 == '\t'; s1++)
;
jname = s1;
s1 = strrchr(s, ' ');
*s1-- = '\0';
s1 = strrchr(s, ' ');
jsize = s1 + 1;
for ( ; *s1 == ' '; s1--)
;
*(s1 + 1) = '\0';
sprintf(buf, "%s|%s|%s|%s@%s|%s|%s|%s\n", printer, jname, jnumber,
owner, hostname, sdate, stime, jsize);
len = strlen(buf);
if (prev_buf_size < (current_size + len + 1))
job_list = (char *) realloc(job_list, (current_size + len + 1) *
sizeof(char *));
memcpy(job_list + current_size, buf, len);
current_size += len;
(*return_n_jobs)++;
}
else
{
if (strstr(s, "down"))
rc = 0;
}
s = strtok(NULL, "\n");
}
*(job_list + current_size) = '\0';
prev_buf_size = prev_buf_size > current_size ? prev_buf_size : current_size;
*return_job_list = job_list;
#ifdef NO_REGCOMP
setlocale(LC_ALL, "");
#endif
delete [] buf;
return rc;
}
/* AIX version 3 and 4 PARSER - have to parse the following
Queue Dev Status Job Name From To
Submitted Rnk Pri Blks Cp PP %
------- ----- --------- --------- --- --- ----- --- ---- --
bsh bshde RUNNING 956 STDIN.14937 root root
08/02/94 09:55:44 1 15 1 1 0 0
/var/spool/qdaemon/tOlkCSM
OR
Queue Dev Status Job Name From To
Submitted Rnk Pri Blks Cp PP %
------- ----- --------- --------- --- --- ----- --- ---- --
john1 lp0 DOWN
QUEUED 957 STDIN.14952 root root
08/02/94 10:17:53 1 15 1 1
/var/spool/qdaemon/tOmgCrx
Also need to parse filenames that are titles: Example, "My Report" below.
QUEUED 957 My Report root root
08/02/94 10:17:53 1 15 1 1
/var/spool/qdaemon/tOmgCrx
*/
int ParseAIXv3PrintJobs(char *_printer, char *jobs,
char **return_job_list, int *return_n_jobs)
{
char *buf = new char[300];
struct stat statbuff;
char *s, *s1, *c;
char *jname;
char *jnumber;
char *owner;
char *sdate;
char *stime;
char *jsize;
char *dollar1;
int current_size;
int len;
char printer[60];
int rc = 1;
static char *job_list = NULL;
static int prev_buf_size = 0;
snprintf(printer, sizeof(printer), "%s", _printer);
if (s = strchr(printer, ':'))
*s = '\0';
if (prev_buf_size == 0)
{
prev_buf_size = BUFSIZ;
job_list = (char *)malloc(prev_buf_size);
}
current_size = 0;
*job_list = '\0';
*return_n_jobs = 0;
s = jobs;
s1 = strchr(s, '\n');
s = s1 + 1;
s1 = strchr(s, '\n');
s = s1 + 1;
s1 = strchr(s, '\n');
s = s1 + 1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
if (strstr(s, "DOWN"))
rc = 0;
while (s && *s)
{
dollar1 = strtok(s, " ");
if (!strncmp(dollar1, printer, strlen(dollar1)))
{
strtok(NULL, " ");
strtok(NULL, " ");
}
jnumber = strtok(NULL, " ");
if (!(jnumber && *jnumber))
{
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
continue;
}
jname = strtok(NULL, "\n");
if (!(jname && *jname))
{
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
continue;
}
for (c = jname + strlen(jname) - 1; *c == ' '; c--)
;
for ( ; *c != ' '; c--)
;
for ( ; *c == ' '; c--)
;
*(c + 1) = '\0';
for ( ; *c != ' '; c--)
;
owner = c + 1;
for ( ; *c == ' '; c--)
;
*(c + 1) = '\0';
for (c = jname; *c == ' '; c++)
;
jname = c;
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
sdate = strtok(s, " ");
stime = strtok(NULL, " ");
strtok(NULL, " ");
strtok(NULL, " ");
jsize = strtok(NULL, " ");
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
c = strtok(s, " \n");
if (strstr(c, jname))
jname = c;
if (!G_AIX_LOCAL)
statbuff.st_size = atoi(jsize) * 512;
else if (stat(c, &statbuff) < 0)
statbuff.st_size = atoi(jsize) * 512;
strtok(owner, ".");
sprintf(buf, "%s|%s|%s|%s|%s|%s|%d\n", printer, jname, jnumber,
owner, sdate, stime, (int)statbuff.st_size);
len = strlen(buf);
if (prev_buf_size < (current_size + len + 1))
job_list = (char *) realloc(job_list, (current_size + len + 1) *
sizeof(char *));
memcpy(job_list + current_size, buf, len);
current_size += len;
(*return_n_jobs)++;
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
}
*(job_list + current_size) = '\0';
prev_buf_size = prev_buf_size > current_size ? prev_buf_size : current_size;
*return_job_list = job_list;
delete [] buf;
return rc;
}
/* AIX version 2 PARSER - have to parse the following
dev arg status request pp output % done
--- ---------- ---------- -------------------- --------- ------
bp0 b906ps5 READY
bp1 s906ps5 READY
bp2 lp0 READY
ts1 t1 OFF
ts2 t2 OFF
queue user request blks cops pri time to
----- ----------------- -------------------- ---- ---- --- ----- --------
ts1 root /etc/motd 2 1 15 15:57 root
ts1 root@warpspeed /etc/rc.afs 3 1 15 16:03 root@war
ts2 root /.profile 1 1 15 16:05 root
ts2 root /.profile 1 1 15 16:06 root
ts2 root@warpspeed /etc/rc.afs 3 1 15 16:07 root@war
*/
int ParseAIXv2PrintJobs(char *printer, char *jobs,
char **return_job_list, int *return_n_jobs)
{
char *buf = new char[300];
char *s, *s1, *c;
char *jname;
char *jnumber;
char *owner;
char *sdate;
char *stime;
char *jsize;
char *device;
char *tmp;
int current_size;
int len;
int rc = 1;
static char *job_list = NULL;
static int prev_buf_size = 0;
if (prev_buf_size == 0)
{
prev_buf_size = BUFSIZ;
job_list = (char *)malloc(prev_buf_size);
}
current_size = 0;
*job_list = '\0';
*return_n_jobs = 0;
sdate = MESSAGE(NotAvailableL);
jnumber = sdate;
s = jobs;
s1 = strchr(s, '\n');
s = s1 + 1;
s1 = strchr(s, '\n');
s = s1 + 1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
while (s)
{
device = strtok(s, " ");
tmp = strtok(NULL, " ");
c = strtok(NULL, " ");
if (!strcmp(tmp, printer))
{
if (strstr(c, "OFF"))
rc = 0;
break;
}
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
}
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
while (s)
{
tmp = strtok(s, " ");
if (!tmp || strcmp(tmp, device))
{
s = s1;
if (s1)
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
continue;
}
owner = strtok(NULL, " ");
jname = strtok(NULL, " ");
jsize = strtok(NULL, " ");
strtok(NULL, " ");
strtok(NULL, " ");
stime = strtok(NULL, " ");
if (c = strchr(owner, '.'))
*c = '\0';
sprintf(buf, "%s|%s|%s|%s|%s|%s|%d\n", printer, jname, jnumber,
owner, sdate, stime, atoi(jsize) * 512);
len = strlen(buf);
if (prev_buf_size < (current_size + len + 1))
job_list = (char *) realloc(job_list, (current_size + len + 1) *
sizeof(char *));
memcpy(job_list + current_size, buf, len);
current_size += len;
(*return_n_jobs)++;
s = s1;
if (s1 = strchr(s, '\n'))
*s1++ = '\0';
}
*(job_list + current_size) = '\0';
prev_buf_size = prev_buf_size > current_size ? prev_buf_size : current_size;
*return_job_list = job_list;
delete [] buf;
return rc;
}