#!/bin/bash#  Used to add/remove printers from system (lp)#  Copyright Fresh Computer Systems Pty Ltd.GREP_OPTIONS='--color=tty'export GREP_OPTIONSsanity() {    #  Are we root?    if [ $EUID != '0' ]; then        exitError You must be root to run this script. 1    fi    if [ ! -x /usr/sbin/lpadmin -a ! -x /sbin/lpadmin ]; then        #  debug        #printf  @@@ ERROR: \'lpadmin\' was not found, or is not executable. Quitting.\n\n        exitError  @@@ ERROR: \'lpadmin\' was not found, or is not executable 1    fi    PPD=/usr/share/cups/model/postscript.ppd    PPDGZ=/usr/share/cups/model/postscript.ppd.gz    if [ -f $PPD ]; then        POSTSCRIPT=$PPD    elif [ -f $PPDGZ ]; then        POSTSCRIPT=$PPDGZ    else        exitError  @@@ ERROR: No postscript file found. Please ensure there is a \$PPD\ or a \$PPDGZ\ file. 1    fi    #  ensure sbin is in path    PATH=/usr/sbin:/sbin:${PATH}    # /etc/hosts file    HOSTS=/etc/hosts    if [ ! -w $HOSTS ]; then        exitError Hosts file \$HOSTS\ is not writeable. 1    fi}exitError() {    #  Provide default exit code '1' if none provided    if [ -n $1 ]; then        ERRMSG=$1        ERRCODE=${2-1}    else        ERRMSG= @@@ ERROR: Unspecified Error.        ERRCODE=${1-1}    fi    ERRMSG=$ERRMSG    printf \n%s\n $ERRMSG   >&2    printf %s\n\n Quitting. >&2    exit ${ERRCODE}}invalidInput() {    declare USELESS    printf \nInvalid input.\n >&2    read -p Press Any Key To Continue... USELESS    #unset USELESS    printf \n}####  FUNCTIONS##enterPrinterName() {    unset PRINTER_TYPE PRINTER_NAME IPADDRESS IPADDRESS_SED CONNECTION_TYPE REPLY RESULT PORTNAME NAME_EXISTS_IN_HOSTS ADDRESS_EXISTS_IN_HOSTS HOSTACTION RC    printf \n    while true; do        read -p Enter printer name, or [q]uit:   PRINTER_NAME        case $PRINTER_NAME in           [qQ])    exitError Aborted by User 0                    ;;            ??*)    break                    ;;           |*)    invalidInput        #blank line or anything else                    ;;        esac    done}checkPrinterExistsInSystem () {    if lpstat -v $PRINTER_NAME 1>/dev/null 2>&1; then        #  Printer already exists in the system        #lpstat -v $PRINTER_NAME        #printf Printer already exists in system!\n >&2        declare EXISTS=0      #true    else        declare EXISTS=1      #false    fi    printf \n    NAME_EXISTS_IN_SYSTEM=$EXISTS    return $EXISTS}checkNameExistsInHosts() {    declare EXISTS=1    #  scan each line from $HOSTS    while read LINE; do        #  Remove comments        LINE=${LINE%%#*}        case $LINE in            *${PRINTER_NAME}*)                #  printer found                EXISTS=0                break #stop looping                ;;            *)                #  printer not found                :                ;;        esac    done < $HOSTS    if [ $EXISTS -eq 0 ]; then        printf Printer \$PRINTER_NAME\ already exists in \$HOSTS\!\n\n >&2        egrep ^[^#]*$PRINTER_NAME[[:space:]]* ${HOSTS}    fi    printf \n    NAME_EXISTS_IN_HOSTS=$EXISTS    return $EXISTS}checkAddressExistsInHosts() {    declare EXISTS=1    while read LINE; do        #  Remove comments        LINE=${LINE%%#*}        case $LINE in            *${IPADDRESS}*)                #  address exists in hosts                EXISTS=0      #true                break                ;;            *)                #  address does not exist                :                ;;        esac    done < $HOSTS    if [ $EXISTS -eq 0 ]; then        #  address exists, add alias        #echo ............. HERE I AM 1 ..............         HOSTACTION=addAliasToHosts        printf IP address \$IPADDRESS\ already exists in \$HOSTS\!\n\n        egrep ^[^#]*$IPADDRESS[[:space:]]* ${HOSTS}    else        #  address is NEW, add as a new host        #echo ............. HERE I AM 2 ..............         HOSTACTION=addHostToHosts    fi    ADDRESS_EXISTS_IN_HOSTS=$EXISTS    printf \n    return $EXISTS}getConnectionType() {    while true; do        #  Connection type        printf \nCONNECTION TYPE:        1. LPD (print server)        2. 9100 (network printer)\n\n        read -p Enter a number, or [q]uit:   REPLY        case $REPLY in          [qQ]) exitError Aborted by User. 0                ;;            1)  CONNECTION_TYPE=LPD                break                ;;            2)  CONNECTION_TYPE=9100                break                ;;         |*)  invalidInput                ;;        esac    done    printf Connection type selected: \$CONNECTION_TYPE\.\n\n    if [ $CONNECTION_TYPE = LPD ]; then        #  LPD connection requires a portname        while true; do            read -p $CONNECTION_TYPE: give portname (e.g. p1), or [q]uit:   REPLY            case $REPLY in                  [qQ]) exitError Aborted by User. 0                        ;;          [[:alnum:]]*) PORTNAME=$REPLY   #at least one alphanumeric char                        break                        ;;                  |*) invalidInput                        ;;            esac        done        printf OK: Portname selected: \$PORTNAME\.\n\n    fi}getPrinterType() {    while true; do        #  Printer Type        read -p Is it a POSTSCRIPT printer, or [q]uit? [y/n/q]          case $REPLY in          [qQ])  exitError Aborted by User. 0                ;;         [yY])  PRINTER_TYPE=postscript                break                ;;         [nN])  PRINTER_TYPE=raw                break                ;;         |*)  invalidInput                ;;        esac    done    printf OK: Printer type selected: \$PRINTER_TYPE\.\n\n}getIpAddr() {    while true; do    read -p Enter full IP address (e.g. 192.168.111.222) of printer \$PRINTER_NAME\, or [q]uit:   REPLY        case $REPLY in            [qQ])    exitError Aborted by User. 0                    ;;        *.*.*.*)    IPADDRESS=$REPLY      #no robust pattern checking...                    break                    ;;           |*)    invalidInput                    ;;        esac    done    printf OK: IP address selected: %s\n\n $IPADDRESS}addHostToHosts() {    if ! [ -w $HOSTS -a -n $IPADDRESS -a -n $PRINTER_NAME ]; then        #  debug        #printf \$HOSTS = $HOSTS\n        #printf \$IPADDRESS = $IPADDRESS\n        #printf \$PRINTER_NAME = $PRINTER_NAME\n        exitError  @@@ ERROR: Error in function \$FUNCNAME\ on line \$LINENO\. 1    fi    #  append host to bottom of $HOSTS    printf %-20s%s\n $IPADDRESS $PRINTER_NAME >> ${HOSTS}    #  show result    egrep \<$IPADDRESS\> $HOSTS    ERROR=$?    return $ERROR}addAliasToHosts() {    if ! [ -w ${HOSTS} -a -n $IPADDRESS -a -n $PRINTER_NAME ]; then        exitError  @@@ ERROR: Error in function \$FUNCNAME\ on line \$LINENO\. 1    fi    #  get IPADDRESS line in $HOSTS    declare PRINTER_NAME_LINE=$(egrep ^[^#]*\<$IPADDRESS\> $HOSTS)    ########    #while read LINE; do    #    #  Remove comments    #    LINE=${LINE%%#*}    #    case $LINE in    #        *${IPADDRESS}*)    #            #  address found    #            declare EXISTS=0    #            break #stop looping    #            ;;    #        *)    #            #  address not found    #            declare EXISTS=1    #            ;;    #    esac    #done < $HOSTS    ########    #  store data (aka remove comments)    declare DATASTORE=${PRINTER_NAME_LINE%%#*}    #  append new printer name to ip address    declare NEW_PRINTER_NAME_LINE=$DATASTORE $PRINTER_NAME    #  store comments (aka remove data)    case $PRINTER_NAME_LINE in        *#*)    declare COMMENTSTORE=${PRINTER_NAME_LINE#*#}                #  append alias to stored data                declare NEW_PRINTER_NAME_LINE=$NEW_PRINTER_NAME_LINE#$COMMENTSTORE                ;;    esac    #  append alias to $HOSTS    printf Appending \$PRINTER_NAME\ to \$HOSTS\ as alias using IP address \$IPADDRESS\.\n\n    sed -r -e s/$PRINTER_NAME_LINE/$NEW_PRINTER_NAME_LINE/ -i $HOSTS    RESULT=$?    #  show result    egrep \<$IPADDRESS\> $HOSTS    return $RESULT}removeFromHosts() {    #  grab line with printer name    declare PRINTER_NAME_LINE=$(egrep ^[^#]*$PRINTER_NAME[[:space:]]* ${HOSTS})    #printf \$PRINTER_NAME_LINE = $PRINTER_NAME_LINE\n    case $PRINTER_NAME_LINE in          *#*)  #  save comment for later (aka delete data)                declare COMMENTSTORE=${PRINTER_NAME_LINE#*#}                declare HASCOMMENT=0 #true                ;;            *)  declare HASCOMMENT=1 #false                ;;    esac    #  store data (aka remove all comments)    declare DATASTORE=${PRINTER_NAME_LINE%%#*}    #printf \$DATASTORE = $DATASTORE\n    #  delete PRINTER_NAME    declare DATASTORE=${DATASTORE/$PRINTER_NAME}    #printf \$DATASTORE = $DATASTORE\n    backupHosts || exit    #  Do we have a host remaining for this IP address?    #  REGEX: ipaddress followed by one or more spaces, followed by one or more alphanumeric chars    if egrep ^[^#]*[[:digit:]]{0,3}\.[[:digit:]]{0,3}\.[[:digit:]]{0,3}\.[[:digit:]]{0,3}[[:space:]]+[[:alnum:]]+ <<<${DATASTORE} >/dev/null 2>&1; then        #  we still have a hostname/alias        if [ $HASCOMMENT -eq 0 ]; then            #  Comment present. Append it.            declare DATASTORE=${DATASTORE}#${COMMENTSTORE}        fi        #  BUG: TODO: this is erasing ALL occurences of printer_name        #  should only modify the one we want        #sed -r -e s/$PRINTER_NAME_LINE[[:space:]]*/$NEW_PRINTER_NAME_LINE/g -i $HOSTS        sed -r -e s/^[^#]*$PRINTER_NAME_LINE[[:space:]]*/$DATASTORE/g -i ${HOSTS}        SED_RESULT=$?    else        #  we have no hostnames/aliases remaining. Delete entire line        #printf  ... running sed ... \n        #printf \$PRINTER_NAME_LINE = $PRINTER_NAME_LINE\n        #printf \$DATASTORE = $DATASTORE\n        sed -r -e /^[^#]*$PRINTER_NAME/d -i $HOSTS        SED_RESULT=$?    fi    if [ $SED_RESULT -eq 0 ]; then        printf Ok: Printer \$PRINTER_NAME\ successfully removed from \$HOSTS\.\n    else        exitError  @@@ ERROR: Fatal error on line \$LINENO\ in function \$FUNCNAME\. 1    fi    return $SED_RESULT    #printf ...reached end of removeFromHosts...\n}backupHosts () {    printf Making backup copy of \$HOSTS\ to \${HOSTS}.$$\.\n    #printf cp -v \${HOSTS}\ \${HOSTS}.$$\\n\n    cp ${HOSTS} ${HOSTS}.$$    RESULT=$?    if [ $RESULT -eq 0 -a -f $HOSTS.$$ ]; then        printf Successfully backed up hosts file.\n\n    else        printf Backup of hosts file was not successful.\n\n >&2    fi    return $RESULT}lpadd() {    COMMANDLINE=lpadmin -p ${PRINTER_NAME} -E    if [ -n ${PRINTER_NAME} -a -n ${PRINTER_TYPE} -a -n ${CONNECTION_TYPE} ]; then        #  PRINTER_TYPE        if [ ${PRINTER_TYPE} = raw ]; then            #  Printer Type: RAW            COMMANDLINE=${COMMANDLINE} -m raw        elif [ $PRINTER_TYPE = postscript ]; then            #  Printer type: postscript            COMMANDLINE=${COMMANDLINE} -P $POSTSCRIPT        else            exitError  @@@ ERROR: Invalid Printer Type: \$PRINTER_TYPE\. 1        fi        #  CONNECTION_TYPE        if [ $CONNECTION_TYPE = LPD ]; then            if [ -n ${PORTNAME} ]; then                COMMANDLINE=${COMMANDLINE} -v lpd://${PRINTER_NAME}/${PORTNAME}            else                exitError Error: Missing \$PORTNAME. 1            fi        elif [ $CONNECTION_TYPE = 9100 ]; then            COMMANDLINE=${COMMANDLINE} -v socket://${PRINTER_NAME}:9100        else            exitError  @@@ ERROR: Invalid Connection Type: \$CONNECTION_TYPE\. 1        fi    else        # debug        echo  -------------------------- *** ---------------------------        echo ----------------- SHOULD NEVER BE HERE ------------------        echo  -------------------------- *** ---------------------------        exitError  @@@ ERROR: Serious error. Insufficient values provided. Function \$FUNCNAME.\ 1        # debug        printf printer name: %s\nprinter type: %s\nconnection type: %s\nportname: %s\n \            $PRINTER_NAME $PRINTER_TYPE $CONNECTION_TYPE $PORTNAME    fi    #  provide error policy    COMMANDLINE=${COMMANDLINE} -o printer-error-policy=retry-job    while true; do        printf About to run this command: \033[1;31m%s\033[0m\n\n ${COMMANDLINE}        read -p Are you sure? 'yes' or [q]uit? [yes/q]   REPLY        case $REPLY in           [qQ])    exitError Aborted by User. 0                    ;;        yes|YES)    break #yes. doAddPrinter                    ;;           |*)    invalidInput                    ;;        esac    done}doAddPrinter() {    declare SUCCESS    #  backup hosts file    backupHosts || exit    #if [ $ADDTOHOSTS = alias ] ; then    #    addAliasToHosts    #else    #    addHostToHosts    #fi    #  add host, or alias    #  debug    #printf \$HOSTACTION = $HOSTACTION\n    eval $HOSTACTION    #  add printer    printf \n    eval $COMMANDLINE    #if eval $COMMANDLINE ; then    if checkPrinterExistsInSystem; then        SUCCESS=0        lpstat -v $PRINTER_NAME        printf Printer successfully added.\n\n    else        SUCCESS=1        printf Printer was not successfully added!\n\n >&2        #exit    fi    return $SUCCESS}acceptPrinter () {    printf Enabling new printer \$PRINTER_NAME\...\n    if which accept >/dev/null 2>&1; then        accept $PRINTER_NAME    elif which cupsenable >/dev/null 2>&1; then        cupsenable $PRINTER_NAME    else        printf Could not enable printer. Try running 'accept $PRINTER_NAME' or 'cupsenable $PRINTER_NAME' manually.\n >&2        false    fi    RC=$?    return $RC}lprm() {    while true; do        read -p Are you sure you want to remove printer \$PRINTER_NAME\? [yes/q]:   REPLY        case $REPLY in            [qQ])   exitError Aborted by User. 0                    ;;         yes|YES)   break                    ;;            |*)   invalidInput                    ;;        esac    done    lpadmin -x ${PRINTER_NAME}            #  delete printer    if checkPrinterExistsInSystem; then     #  does printer still exist?        #  printer remains -- bad        declare SUCCESS=1     #false    else        #  printer deleted -- good        declare SUCCESS=0     #true        #FIXME        removeFromHosts    fi    return $SUCCESS}main () {    enterPrinterName    if checkPrinterExistsInSystem; then        lpstat -v ${PRINTER_NAME}        printf \nPrinter \${PRINTER_NAME}\ already exists in the system.\n        while true; do            read -p [d]elete printer, [r]estart, or [q]uit? [r/s/q]?   REPLY            case $REPLY in                [qQ])   exitError Aborted by User. 0                        ;;                [dD])   if lprm $PRINTER_NAME; then                            printf OK: Printer \${PRINTER_NAME}\ successfully removed from the system.\n\n                            #break       #call checkNameExistsInHosts                            return 0                        else                            exitError  @@@ ERROR: Failure to remove printer from the system.\n 1                        fi                        ;;                [rR])   return 0    #exit main, start loop again, restart script                        ;;            esac        done    else        # consider deleting completely        : #printf OK: Printer \${PRINTER_NAME}\ does not exist in the system.\n\n    fi    if checkNameExistsInHosts; then        while true; do            read -p Are the details correct [y], [r]estart or [q]uit? [y/r/q]   REPLY            case $REPLY in               [qQ])    exitError Aborted by User. 0                        ;;               [yY])    #if ok -> getData()                        break                        ;;               [rR])    #if not ok -> loop back main                        printf OK: Restarting script.\n\n                        return 0 #quit main and restart script                        ;;               |*)    invalidInput                        ;;            esac        done    else        #if name does not exist in hosts, get ip addr        getIpAddr        if checkAddressExistsInHosts; then            while true; do                read -p Add as an alias to \$HOSTS\, or [q]uit? [y/n/q]   REPLY                case $REPLY in                    [qQnN]) exitError Aborted by User. 0                            ;;                    [yY])   break #addAliasToHosts                            ;;                   |*)    invalidInput                            ;;                esac            done        fi    fi    getConnectionType    getPrinterType    lpadd    doAddPrinter    acceptPrinter}####  MAIN PROGRAM##sanitywhile true; do    maindoneunset GREP_OPTIONS
bash script for printer administration
bash