*---------------------------------------------------------------------- * Program Name: ZBC_O_PRINTER_CONTROL_REPORT * Date Written: July 2007 * Author : WATSONMI * Description : Enable SAP system administrators to view the status * of UNIX printer queues without having to log onto UNIX. * Also allows queues to started and stopped as well as * the cancelling of print jobs. * * Tested successfully on AIX, with additional commands to * run on SunOS boxes. *---------------------------------------------------------------------- * MODIFICATIONS * Transport Date Description * OSDK940347 19/07/07 -Rewrote entire program * -Added in support for AIX * OSDK940896 10/09/07 -Added in additional line detections * -Displays error messages *---------------------------------------------------------------------- REPORT zbc_o_printer_control_report MESSAGE-ID zbc_o LINE-SIZE 130 NO STANDARD PAGE HEADING. ************************************************************************ *** *** VARIABLES *** ************************************************************************ *** INTERNAL TABLES *** TYPES: BEGIN OF t_printers, shortname LIKE tsp03l-lname, longname LIKE tsp03l-lname, queue LIKE tsp03c-paprosname, device LIKE tsp03-patype, desc LIKE tsp03-pastandort, END OF t_printers. DATA: v_printers TYPE t_printers, i_printers TYPE SORTED TABLE OF t_printers WITH UNIQUE KEY longname. TYPES: BEGIN OF t_output, line(132) TYPE c, END OF t_output. DATA: v_output TYPE t_output, i_output TYPE STANDARD TABLE OF t_output, i_output_command TYPE STANDARD TABLE OF t_output. *** VARIABLES *** DATA: v_job_id(60) TYPE c, v_command(80) TYPE c. *** CONSTANTS *** DATA: v_command_queue_aix(64) TYPE c VALUE 'lpq -P ', v_command_queue_sun(64) TYPE c VALUE 'lpstat -o 2>&1', v_command_status(64) TYPE c VALUE 'lpstat -p ', v_command_restart(64) TYPE c VALUE '/usr/bin/sudo -u lp /usr/ucb/lpc start ', v_command_disable(64) TYPE c VALUE 'sudo -u lp /bin/disable -r "" ', v_command_cancel(64) TYPE c VALUE 'sudo -u lp /bin/cancel ', v_command_abort(64) TYPE c VALUE '/usr/bin/sudo -u lp /usr/ucb/lpc abort '. *---------------------------------------------------------------------* * START-OF-SELECTION *---------------------------------------------------------------------* START-OF-SELECTION. * Check that the user is allowed to use the SPAD tansaction AUTHORITY-CHECK OBJECT 'S_ADMI_FCD' ID 'S_ADMI_FCD' FIELD 'SPAD'. IF sy-subrc <> 0. MESSAGE e005. ENDIF. FORMAT INTENSIFIED OFF. * get the printers SELECT tsp03l~padest tsp03l~lname tsp03c~paprosname tsp03~patype tsp03~pastandort INTO TABLE i_printers FROM tsp03 JOIN tsp03c ON tsp03~padest = tsp03c~padest JOIN tsp03l ON tsp03l~padest = tsp03~padest. LOOP AT i_printers INTO v_printers. IF v_printers-queue CA ' '. v_printers-queue = v_printers-queue(sy-fdpos). ENDIF. WRITE: / '|', v_printers-longname INTENSIFIED, '|', v_printers-shortname(4), '|', v_printers-queue(8), '|', v_printers-device, '|', v_printers-desc, '|'. HIDE: v_printers. ENDLOOP. ULINE. *---------------------------------------------------------------------* * AT LINE-SELECTION *---------------------------------------------------------------------* AT LINE-SELECTION. PERFORM display_printer. *---------------------------------------------------------------------* * AT USER-COMMAND *---------------------------------------------------------------------* AT USER-COMMAND. CASE sy-ucomm. WHEN 'RSTR'. PERFORM restart_queue. WHEN 'DISB'. PERFORM disable_queue. WHEN 'CANC'. PERFORM cancel_job. WHEN 'RFSH'. PERFORM refresh_queue. WHEN 'PRIN'. PERFORM print_test. WHEN 'ABRT'. PERFORM abort_queue. ENDCASE. *---------------------------------------------------------------------* * TOP-OF-PAGE *---------------------------------------------------------------------* TOP-OF-PAGE. ULINE. WRITE: / '| Printer Name | Name |UNIX Queue|DeviceType| Description |'. ULINE. *---------------------------------------------------------------------* * FORM BUILD_COMMAND *---------------------------------------------------------------------* * [+] Replaces keywords in the v_command with their correct values *---------------------------------------------------------------------* FORM build_command USING p_command. v_command = p_command. REPLACE '' WITH v_printers-queue INTO v_command. REPLACE '' WITH v_job_id INTO v_command. ENDFORM. "build_command *---------------------------------------------------------------------* * FORM RUN_COMMAND *---------------------------------------------------------------------* * [+] Runs the v_command on the server (unix level) *---------------------------------------------------------------------* FORM run_command USING p_command. REFRESH: i_output. CLEAR: i_output, v_output. CONDENSE p_command. CALL FUNCTION 'RFC_REMOTE_PIPE' DESTINATION 'SERVER_EXEC_DB' EXPORTING command = p_command read = 'X' TABLES pipedata = i_output EXCEPTIONS system_failure = 1 communication_failure = 2 OTHERS = 99. ENDFORM. "run_command *---------------------------------------------------------------------* * FORM WRITE_PRINTER_DETAILS *---------------------------------------------------------------------* * [+] Writes the status and queue details for the printer *---------------------------------------------------------------------* FORM write_printer_details. IF sy-opsys = 'AIX'. PERFORM write_printer_details_aix. ELSE. PERFORM write_printer_details_sun. ENDIF. ENDFORM. "write_printer_details *---------------------------------------------------------------------* * FORM WRITE_PRINTER_DETAILS_AIX *---------------------------------------------------------------------* * [+] Writes the status and queue details for the printer (AIX system) *---------------------------------------------------------------------* FORM write_printer_details_aix. DATA: lv_name(100) TYPE c, lv_enabled(100) TYPE c, lv_available(100) TYPE c, lv_timestamp(100) TYPE c. CONCATENATE v_printers-longname '(' v_printers-shortname ')' INTO lv_name SEPARATED BY space. WRITE: / 'Printer:', AT 12 lv_name, / 'Queue:', AT 12 v_printers-queue. PERFORM build_command USING v_command_status. PERFORM run_command USING v_command. LOOP AT i_output INTO v_output. SEARCH v_output-line FOR '.onesteel.com'. IF sy-subrc = 0. * skip over the dots in the web address SPLIT v_output-line AT '.' INTO v_output-line v_output-line v_output-line. ENDIF. SPLIT v_output-line AT '.' INTO lv_name lv_enabled lv_available. CONDENSE: lv_enabled, lv_available. SPLIT lv_enabled AT ' ' INTO lv_enabled lv_timestamp lv_timestamp. PERFORM capital_letter CHANGING lv_enabled. PERFORM capital_letter CHANGING lv_available. CONCATENATE lv_enabled 'at' lv_timestamp INTO lv_enabled SEPARATED BY space. WRITE: / 'Status:', AT 12 lv_enabled, / 'Ready:', AT 12 lv_available. * Only want the first line of the output for the status EXIT. ENDLOOP. ULINE. ENDFORM. "write_printer_details *---------------------------------------------------------------------* * FORM WRITE_PRINTER_DETAILS_SUN *---------------------------------------------------------------------* * [+] Writes the status and queue details for the printer (Solaris system) *---------------------------------------------------------------------* FORM write_printer_details_sun. DATA: lv_name(100) TYPE c, lv_enabled(100) TYPE c, lv_available(100) TYPE c, lv_timestamp(100) TYPE c. CONCATENATE v_printers-longname '(' v_printers-shortname ')' INTO lv_name SEPARATED BY space. WRITE: / 'Printer:', AT 12 lv_name, / 'Queue:', AT 12 v_printers-queue. PERFORM build_command USING v_command_status. PERFORM run_command USING v_command. LOOP AT i_output INTO v_output. CLEAR: lv_name, lv_enabled, lv_available. SPLIT v_output-line AT '.' INTO lv_name lv_enabled lv_available. IF lv_available IS INITIAL. * disabled or waiting status lv_available = lv_enabled. SPLIT lv_name AT ' ' INTO lv_name lv_name lv_enabled. ENDIF. CONDENSE: lv_enabled, lv_available. IF lv_enabled(7) = 'waiting'. * waiting status CLEAR lv_timestamp. ELSE. * enabled or disabled status SPLIT lv_enabled AT ' ' INTO lv_enabled lv_timestamp lv_timestamp. CONCATENATE lv_enabled 'at' lv_timestamp INTO lv_enabled SEPARATED BY space. ENDIF. PERFORM capital_letter CHANGING lv_enabled. PERFORM capital_letter CHANGING lv_available. WRITE: / 'Status:', AT 12 lv_enabled, / 'Ready:', AT 12 lv_available. * Only want the first line of the output for the status EXIT. ENDLOOP. ULINE. ENDFORM. "write_printer_details *---------------------------------------------------------------------* * FORM DISPLAY_PRINTER *---------------------------------------------------------------------* * [+] Displays the details and queue for a specific printer *---------------------------------------------------------------------* FORM display_printer. SET PF-STATUS 'QUE'. PERFORM write_printer_details. PERFORM display_queue. ULINE. ENDFORM. "display_printer *---------------------------------------------------------------------* * FORM DISPLAY_QUEUE *---------------------------------------------------------------------* * [+] Displays the queue for a specific printer *---------------------------------------------------------------------* FORM display_queue. IF sy-opsys = 'AIX'. PERFORM display_queue_aix. ELSE. PERFORM display_queue_sun. ENDIF. ENDFORM. "display_queue *---------------------------------------------------------------------* * FORM DISPLAY_QUEUE_AIX *---------------------------------------------------------------------* * [+] Displays the queue for a specific printer (AIX System) *---------------------------------------------------------------------* FORM display_queue_aix. DATA: lv_line_type(20) TYPE c, lv_end_message(100) TYPE c, lv_user(30) TYPE c, lv_class(1) TYPE c, lv_job(5) TYPE c, lv_rank(8) TYPE c, lv_files(50) TYPE c, lv_size(10) TYPE c, lv_time(8) TYPE c, lv_dummy(100) TYPE c, lv_printer(30) TYPE c, lv_char_13(1) TYPE c, lv_error_32(32) TYPE c, lv_error_65(65) TYPE c. PERFORM make_hex_value USING '0D' CHANGING lv_char_13. lv_end_message = 'No jobs in the queue'. PERFORM build_command USING v_command_queue_aix. PERFORM run_command USING v_command. LOOP AT i_output INTO v_output. * remove leading spaces CONDENSE v_output-line. * determine the type of data in the output line. SPLIT v_output-line AT ' ' INTO lv_line_type v_output-line. CASE lv_line_type. WHEN 'Printer:'. * get the printer name SPLIT v_output-line AT ' ' INTO lv_printer v_output-line. * check to see if there is an error. SEARCH v_output-line FOR 'ERROR:'. IF sy-subrc = 0. SEARCH v_output-line FOR 'spool queue'. IF sy-subrc = 0. * Spool queue error lv_end_message = 'The spool queue is not defined on the server'. ELSE. * Other error SPLIT v_output-line AT 'ERROR: ' INTO v_output-line v_output-line. CONCATENATE 'The printer' lv_printer 'has an error:' v_output-line INTO lv_end_message SEPARATED BY space. PERFORM capital_letter CHANGING lv_end_message. ENDIF. EXIT. ENDIF. WHEN 'JetDirect'. SEARCH v_output-line FOR 'no jobs queued'. IF sy-subrc = 0. IF lv_end_message IS NOT INITIAL. lv_end_message = 'No jobs in the queue'. ENDIF. EXIT. ENDIF. * want to ignore all these lines WHEN 'Queue:'. WHEN 'queue'. WHEN 'Queue'. WHEN 'Online/Offline'. WHEN '(LPD'. WHEN '(P1)STATE:'. WHEN 'TYPE:'. WHEN 'PRINTER'. WHEN 'Printer'. WHEN 'Active'. WHEN 'Server:'. WHEN 'Unspooler:'. WHEN 'Status:'. WHEN 'Status'. WHEN 'Sleeping'. WHEN 'status:'. WHEN 'Waiting'. WHEN 'Ready'. WHEN 'Drum'. WHEN 'EasyCoder'. WHEN 'printing'. WHEN 'Printing'. WHEN 'no'. WHEN 'No'. WHEN 'target:'. WHEN 'Rank'. WHEN '--'. WHEN ''. WHEN lv_char_13. WHEN OTHERS. lv_rank = lv_line_type. * Make a more detailed rank message SEARCH lv_line_type FOR '(attempt-'. IF sy-subrc = 0. SPLIT lv_line_type AT '-' INTO lv_rank lv_rank. CONCATENATE 'Try' lv_rank(1) INTO lv_rank SEPARATED BY space. ENDIF. SEARCH lv_line_type FOR 'stalled('. IF sy-subrc = 0. lv_rank = 'Stalled'. ENDIF. * ignore all these lines - they are inline status messages SEARCH lv_line_type FOR 'KCA_'. IF sy-subrc = 0. CONTINUE. ENDIF. SEARCH lv_line_type FOR 'no entries'. IF sy-subrc = 0. CONTINUE. ENDIF. SEARCH lv_line_type FOR 'Active'. IF sy-subrc = 0. CONTINUE. ENDIF. SEARCH lv_line_type FOR 'Waiting'. IF sy-subrc = 0. CONTINUE. ENDIF. * Split the output line into the details SPLIT v_output-line AT ' ' INTO lv_user lv_class lv_job lv_files lv_size lv_time. * remove the job number from the username SPLIT lv_user AT '+' INTO lv_user lv_dummy. * Connection Timeout errors IF lv_line_type = 'error'. IF lv_end_message IS NOT INITIAL. * write out the headings PERFORM write_queue_header_aix. ENDIF. CLEAR: lv_end_message. * split out the error message SPLIT v_output-line AT ' ' INTO lv_dummy lv_dummy lv_dummy lv_dummy lv_error_32. WRITE: / '|', lv_job, '|', lv_printer, '|', lv_user, '|', lv_error_32 COLOR COL_NEGATIVE, '|'. CLEAR: lv_error_32. * Other errors like bad connection and host lookups ELSEIF lv_line_type = 'Printer'. SPLIT v_output-line AT ' ' INTO lv_dummy lv_dummy lv_error_65. lv_job = '0'. * ignore the Idle status messages SEARCH lv_error_65 FOR 'Idle.'. IF sy-subrc = 0. CLEAR lv_error_65. ENDIF. IF lv_error_65 IS NOT INITIAL. IF lv_end_message IS NOT INITIAL. * write out the headings PERFORM write_queue_header_aix. ENDIF. CLEAR: lv_end_message. WRITE: / '|', lv_job, '|', lv_printer, '|', lv_error_65 COLOR COL_NEGATIVE, '|'. ENDIF. CLEAR: lv_error_65. * A normal queue line ELSE. IF lv_end_message IS NOT INITIAL. * write out the headings PERFORM write_queue_header_aix. ENDIF. CLEAR: lv_end_message. PERFORM capital_letter CHANGING lv_rank. * A 'Done' entry in the queue IF lv_rank = 'Done'. WRITE: / '|', lv_job, '|', lv_printer, '|', lv_user, '|', lv_time, '|', lv_size, '|', lv_rank COLOR COL_POSITIVE, '|'. * A 'waiting' entry in the queue ELSE. WRITE: / '|', lv_job, '|', lv_printer, '|', lv_user, '|', lv_time, '|', lv_size, '|', lv_rank, '|'. ENDIF. ENDIF. * Remember the job id (for cancelling, etc). v_job_id = lv_job. HIDE v_job_id. ENDCASE. ENDLOOP. IF lv_end_message IS NOT INITIAL. WRITE: / lv_end_message. ELSE. * write out the bottom line of the queue table WRITE: / '--------------------------------------------------------------------------------------------------------------'. ENDIF. CLEAR v_job_id. ENDFORM. "DISPLAY_UNIX_PRINTS_QUEUED *---------------------------------------------------------------------* * FORM DISPLAY_QUEUE_SUN *---------------------------------------------------------------------* * [+] Displays the queue for a specific printer (Solaris System) *---------------------------------------------------------------------* FORM display_queue_sun. DATA: lv_end_message(100) TYPE c, lv_user(30) TYPE c, lv_job(5) TYPE c, lv_size(10) TYPE c, lv_time(12) TYPE c, lv_printer(30) TYPE c. lv_end_message = 'No items in the queue'. PERFORM build_command USING v_command_queue_sun. PERFORM run_command USING v_command. LOOP AT i_output INTO v_output. * remove leading spaces CONDENSE v_output-line. IF lv_end_message IS NOT INITIAL. * write out the headings WRITE: / '-------------------------------------------------------------------------------------------------------', / '| Job | Printer Name | User | Time | Size |', / '-------------------------------------------------------------------------------------------------------'. ENDIF. CLEAR: lv_end_message. * Split the output line into the details SPLIT v_output-line AT ' ' INTO lv_printer lv_user lv_size lv_time. * get the job number from the printer name SPLIT lv_printer AT '-' INTO lv_printer lv_job. * A line in the queue WRITE: / '|', lv_job, '|', lv_printer, '|', lv_user, '|', lv_time, '|', lv_size, '|'. * Remember the job id (for cancelling, etc). v_job_id = lv_job. HIDE v_job_id. ENDLOOP. IF lv_end_message IS NOT INITIAL. WRITE: / lv_end_message. ELSE. * write out the bottom line of the queue table WRITE: / '-------------------------------------------------------------------------------------------------------'. ENDIF. CLEAR v_job_id. ENDFORM. "DISPLAY_UNIX_PRINTS_QUEUED *---------------------------------------------------------------------* * FORM RESTART_QUEUE *---------------------------------------------------------------------* * [+] Sends the RESTART command *---------------------------------------------------------------------* FORM restart_queue. PERFORM build_command USING v_command_restart. PERFORM run_command USING v_command. PERFORM write_command_output. ENDFORM. "restart_queue *---------------------------------------------------------------------* * FORM DISABLE_QUEUE *---------------------------------------------------------------------* * [+] Sends the DISABLE command *---------------------------------------------------------------------* FORM disable_queue. PERFORM build_command USING v_command_disable. PERFORM run_command USING v_command. PERFORM write_command_output. ENDFORM. "disable_queue *---------------------------------------------------------------------* * FORM CANCEL_JOB *---------------------------------------------------------------------* * [+] Sends the CANCEL command for the selected job *---------------------------------------------------------------------* FORM cancel_job. IF v_job_id IS INITIAL. EXIT. ENDIF. PERFORM build_command USING v_command_cancel. PERFORM run_command USING v_command. PERFORM write_command_output. ENDFORM. "cancel_job *---------------------------------------------------------------------* * FORM ABORT_QUEUE *---------------------------------------------------------------------* * [+] Sends the ABORT command *---------------------------------------------------------------------* FORM abort_queue. PERFORM build_command USING v_command_abort. PERFORM run_command USING v_command. PERFORM write_command_output. ENDFORM. " abort_queue *---------------------------------------------------------------------* * FORM REFRESH_QUEUE *---------------------------------------------------------------------* * [+] Reloads the details of the current printer *---------------------------------------------------------------------* FORM refresh_queue. * So this page overwrites the previous SUBTRACT 1 FROM sy-lsind. PERFORM display_printer. ENDFORM. "refresh_queue *---------------------------------------------------------------------* * FORM PRINT_TEST *---------------------------------------------------------------------* * [+] Prints a test page to the printer *---------------------------------------------------------------------* FORM print_test. NEW-PAGE PRINT ON DESTINATION v_printers-shortname IMMEDIATELY 'X' NO DIALOG SAP COVER PAGE ' ' KEEP IN SPOOL 'X'. SKIP 4. WRITE: / ' SSSSSSSSSS AAAAAAAAAA PPPPPPPPPPP ', / ' SSSSSSSSSSSS AAAAAAAAAAAA PPPPPPPPPPPP ', / ' SS AAA AAA PP PP ', / ' SS AA AA PP PP ', / ' SSS AA AA PP PP ', / ' SSSSSSSSS AAAAAAAAAAAAAA PPPPPPPPPPPP ', / ' SSSSSSSSS AAAAAAAAAAAAAA PPPPPPPPPPP ', / ' SSS AA AA PP ', / ' SS AA AA PP ', / ' SS SS AA AA PP ', / ' SSSSSSSSSSSS AA AA PP ', / ' SSSSSSSSSS AA AA PP '. SKIP 2. WRITE: / ' TTTTTTTTTTTT EEEEEEEEEEEE SSSSSSSSSS TTTTTTTTTTTT ', / ' TTTTTTTTTTTT EEEEEEEEEEEE SSSSSSSSSSSS TTTTTTTTTTTT ', / ' TT EE SS TT ', / ' TT EE SS TT ', / ' TT EE SSS TT ', / ' TT EEEEEEEE SSSSSSSSS TT ', / ' TT EEEEEEEE SSSSSSSSS TT ', / ' TT EE SSS TT ', / ' TT EE SS TT ', / ' TT EE SS SS TT ', / ' TT EEEEEEEEEEEE SSSSSSSSSSSS TT ', / ' TT EEEEEEEEEEEE SSSSSSSSSS TT '. SKIP 4. WRITE: / text-021, 10 v_printers-shortname, 20 text-022, 28 sy-uzeit USING EDIT MASK '__:__'. NEW-PAGE PRINT OFF. * write info out to the screen, saying print started. REFRESH: i_output. CLEAR: i_output, v_output. v_output-line = 'Printer: Test print sent to printer'. APPEND v_output TO i_output. APPEND v_output TO i_output. "attach twice, so it is written below PERFORM write_command_output. ENDFORM. "print_test *---------------------------------------------------------------------* * FORM WRITE_COMMAND_OUTPUT *---------------------------------------------------------------------* * [+] Writes the output of a command to the screen *---------------------------------------------------------------------* FORM write_command_output. DATA: lv_num_lines TYPE i, lv_dummy(100) TYPE c. i_output_command = i_output. PERFORM refresh_queue. DESCRIBE TABLE i_output_command LINES lv_num_lines. IF lv_num_lines = 2. * most normal outputs READ TABLE i_output_command INDEX 2 INTO v_output. SPLIT v_output-line AT ' ' INTO v_output-line v_output-line. PERFORM capital_letter CHANGING v_output-line. WRITE: / 'Command Results: ', v_output-line(80). ELSEIF lv_num_lines = 4. * Cancelling a job READ TABLE i_output_command INDEX 3 INTO v_output. CONDENSE v_output-line. SPLIT v_output-line AT ' ' INTO v_output-line lv_dummy. PERFORM capital_letter CHANGING v_output-line. WRITE: / 'Command Results: ', v_output-line(80). ELSE. * anything else LOOP AT i_output_command INTO v_output. WRITE: / v_output-line. ENDLOOP. ENDIF. ULINE. ENDFORM. " abort_queue *---------------------------------------------------------------------* * FORM CAPITAL_LETTER *---------------------------------------------------------------------* * [+] Changes the first letter of the p_string to a capital *---------------------------------------------------------------------* FORM capital_letter CHANGING p_string. DATA: lv_first_letter(1) TYPE c. lv_first_letter = p_string(1). TRANSLATE lv_first_letter TO UPPER CASE. WRITE lv_first_letter TO p_string+0(1). ENDFORM. "capital_letter *---------------------------------------------------------------------* * FORM MAKE_HEX_VALUE *---------------------------------------------------------------------* * [+] Makes a p_char representation of the given p_hex value *---------------------------------------------------------------------* FORM make_hex_value USING p_hex TYPE x CHANGING p_char TYPE c. DATA: BEGIN OF lv_char_hex, value TYPE x, END OF lv_char_hex. lv_char_hex-value = p_hex. WRITE lv_char_hex TO p_char. ENDFORM. " make_hex_value *---------------------------------------------------------------------* * FORM WRITE_QUEUE_HEADER_AIX *---------------------------------------------------------------------* * [+] Write out the queue headings (AIX system) *---------------------------------------------------------------------* FORM write_queue_header_aix. WRITE: / '--------------------------------------------------------------------------------------------------------------', / '| Job | Printer Name | User | Time | Size | Rank |', / '--------------------------------------------------------------------------------------------------------------'. ENDFORM. "write_queue_header_aix