/* * 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 #include #include #include #include #if defined(_AIX) /* * XXXXX - AIX hack alert!!! This is needed for an AIX defect * in the definition of inet_addr in */ extern "C" in_addr_t inet_addr(const char *); #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "dtprintinfomsg.h" #ifdef NO_REGCOMP #include #if defined(SVR4) || defined(SYSV) #include #endif #else #include #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] 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; }