All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sshd.common.channel.PtyMode Maven / Gradle / Ivy

There is a newer version: 2.14.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.sshd.common.channel;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.function.Function;
import java.util.function.ToIntFunction;

import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.MapEntryUtils;

/**
 * A enum describing the tty modes according to RFC 4254 -
 * section 8.
 *
 * @author Apache MINA SSHD Project
 */
public enum PtyMode {

    /////////////////////////////// Chars ////////////////////////////////////

    /**
     * Interrupt character; 255 if none. Similarly for the other characters. Not all of these characters are supported
     * on all systems.
     */
    VINTR(1),
    /**
     * The quit character (sends SIGQUIT signal on POSIX systems).
     */
    VQUIT(2),
    /**
     * Erase the character to left of the cursor.
     */
    VERASE(3),
    /**
     * Kill the current input line.
     */
    VKILL(4),
    /**
     * End-of-file character (sends EOF from the terminal).
     */
    VEOF(5),
    /**
     * End-of-line character in addition to carriage return and/or line-feed.
     */
    VEOL(6),
    /**
     * Additional end-of-line character.
     */
    VEOL2(7),
    /**
     * Continues paused output (normally control-Q).
     */
    VSTART(8),
    /**
     * Pauses output (normally control-S).
     */
    VSTOP(9),
    /**
     * Suspends the current program.
     */
    VSUSP(10),
    /**
     * Another suspend character.
     */
    VDSUSP(11),
    /**
     * Reprints the current input line.
     */
    VREPRINT(12),
    /**
     * Erases a word left of cursor.
     */
    VWERASE(13),
    /**
     * Enter the next character typed literally, even if it is a special character
     */
    VLNEXT(14),
    /**
     * Character to flush output.
     */
    VFLUSH(15),
    /**
     * Switch to a different shell layer.
     */
    VSWTCH(16),
    /**
     * Prints system status line (load, command, pid, etc).
     */
    VSTATUS(17),
    /**
     * Toggles the flushing of terminal output.
     */
    VDISCARD(18),

    ///////////////////////////////// I-flags ////////////////////////////////

    /**
     * The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE, and 1 if it is TRUE.
     */
    IGNPAR(30),
    /**
     * Mark parity and framing errors.
     */
    PARMRK(31),
    /**
     * Enable checking of parity errors.
     */
    INPCK(32),
    /**
     * Strip 8th bit off characters.
     */
    ISTRIP(33),
    /**
     * Map NL into CR on input.
     */
    INLCR(34),
    /**
     * Ignore CR on input.
     */
    IGNCR(35),
    /**
     * Map CR to NL on input.
     */
    ICRNL(36),
    /**
     * Translate uppercase characters to lowercase.
     */
    IUCLC(37),
    /**
     * Enable output flow control.
     */
    IXON(38),
    /**
     * Any char will restart after stop.
     */
    IXANY(39),
    /**
     * Enable input flow control.
     */
    IXOFF(40),
    /**
     * Ring bell on input queue full.
     */
    IMAXBEL(41),
    /**
     * @see IUTF8 Terminal Mode in Secure Shell
     */
    IUTF8(42),

    /////////////////////////////// L-flags //////////////////////////////////

    /**
     * Enable signals INTR, QUIT, [D]SUSP.
     */
    ISIG(50),
    /**
     * Canonicalize input lines.
     */
    ICANON(51),
    /**
     * Enable input and output of uppercase characters by preceding their lowercase equivalents with "\".
     */
    XCASE(52),
    /**
     * Enable echoing.
     */
    ECHO(53),
    /**
     * Visually erase chars.
     */
    ECHOE(54),
    /**
     * Kill character discards current line.
     */
    ECHOK(55),
    /**
     * Echo NL even if ECHO is off.
     */
    ECHONL(56),
    /**
     * Don't flush after interrupt.
     */
    NOFLSH(57),
    /**
     * Stop background jobs from output.
     */
    TOSTOP(58),
    /**
     * Enable extensions.
     */
    IEXTEN(59),
    /**
     * Echo control characters as ^(Char).
     */
    ECHOCTL(60),
    /**
     * Visual erase for line kill.
     */
    ECHOKE(61),
    /**
     * Retype pending input.
     */
    PENDIN(62),

    /////////////////////////// O-flags //////////////////////////////////////

    /**
     * Enable output processing.
     */
    OPOST(70),
    /**
     * Convert lowercase to uppercase.
     */
    OLCUC(71),
    /**
     * Map NL to CR-NL.
     */
    ONLCR(72),
    /**
     * Translate carriage return to newline (output).
     */
    OCRNL(73),
    /**
     * Translate newline to carriage return-newline (output).
     */
    ONOCR(74),
    /**
     * Newline performs a carriage return (output).
     */
    ONLRET(75),

    //////////////////////////////// C-flags /////////////////////////////////

    /**
     * 7 bit mode.
     */
    CS7(90),
    /**
     * 8 bit mode.
     */
    CS8(91),
    /**
     * Parity enable.
     */
    PARENB(92),
    /**
     * Odd parity, else even.
     */
    PARODD(93),

    /////////////////////////// Speed(s) /////////////////////////////////////

    /**
     * Specifies the input baud rate in bits per second.
     */
    TTY_OP_ISPEED(128),
    /**
     * Specifies the output baud rate in bits per second.
     */
    TTY_OP_OSPEED(129);

    public static final byte TTY_OP_END = 0x00;

    // objects that can be used to set {@link PtyMode}s as {@code true} or {@code false}
    public static final Integer FALSE_SETTING = 0;
    public static final Integer TRUE_SETTING = 1;

    /**
     * An un-modifiable {@link Set} of all defined {@link PtyMode}s
     */
    public static final Set MODES = Collections.unmodifiableSet(EnumSet.allOf(PtyMode.class));

    public static final NavigableMap COMMANDS = Collections.unmodifiableNavigableMap(
            MapEntryUtils.toSortedMap(MODES, PtyMode::toInt, Function.identity(), Comparator.naturalOrder()));

    /**
     * A {@code null}-safe {@link ToIntFunction} that returns the {@link PtyMode#toInt()} value and (-1) for
     * {@code null}
     */
    public static final ToIntFunction OPCODE_EXTRACTOR = op -> (op == null) ? -1 : op.toInt();

    /**
     * A {@code null}-safe {@link Comparator} of {@link PtyMode} values according to their {@link PtyMode#toInt()} value
     *
     * @see #OPCODE_EXTRACTOR
     */
    public static final Comparator BY_OPCODE = (o1, o2) -> {
        int v1 = OPCODE_EXTRACTOR.applyAsInt(o1);
        int v2 = OPCODE_EXTRACTOR.applyAsInt(o2);
        return Integer.compare(v1, v2);
    };

    private final int v;

    PtyMode(int v) {
        this.v = v;
    }

    public int toInt() {
        return v;
    }

    /**
     * @param  b The numeric value of the option
     * @return   The matching {@link PtyMode} or {@code null} if no match found
     * @see      #toInt()
     */
    public static PtyMode fromInt(int b) {
        return COMMANDS.get(0x00FF & b);
    }

    public static PtyMode fromName(String name) {
        if (GenericUtils.isEmpty(name)) {
            return null;
        }

        for (PtyMode m : MODES) {
            if (name.equalsIgnoreCase(m.name())) {
                return m;
            }
        }

        return null;
    }

    /**
     * @param  options The options to enable - ignored if {@code null}/empty
     * @return         A {@link Map} where all the specified {@link PtyMode}s have {@link #TRUE_SETTING}
     */
    public static Map createEnabledOptions(PtyMode... options) {
        return createEnabledOptions(GenericUtils.of(options));
    }

    /**
     * @param  options The options to enable - ignored if {@code null}/empty
     * @return         A {@link Map} where all the specified {@link PtyMode}s have {@link #TRUE_SETTING}
     */
    public static Map createEnabledOptions(Collection options) {
        if (GenericUtils.isEmpty(options)) {
            return Collections.emptyMap();
        }

        Map modes = new EnumMap<>(PtyMode.class);
        for (PtyMode m : options) {
            modes.put(m, TRUE_SETTING);
        }

        return modes;
    }

    public static Set resolveEnabledOptions(Map modes, PtyMode... options) {
        return resolveEnabledOptions(modes, GenericUtils.of(options));
    }

    /**
     * @param  modes   The PTY settings - ignored if {@code null}/empty
     * @param  options The options that should be enabled
     * @return         A {@link Set} of all the {@link PtyMode}s that appeared in the settings and were enabled
     * @see            #getBooleanSettingValue(Map, PtyMode)
     */
    public static Set resolveEnabledOptions(Map modes, Collection options) {
        if (MapEntryUtils.isEmpty(modes) || GenericUtils.isEmpty(options)) {
            return Collections.emptySet();
        }

        Set enabled = EnumSet.noneOf(PtyMode.class);
        for (PtyMode m : options) {
            if (getBooleanSettingValue(modes, m)) {
                enabled.add(m);
            }
        }

        return enabled;
    }

    /**
     * @param  modes The current modes {@link Map}-ing
     * @param  m     The required {@link PtyMode}
     * @return       {@code true} if all of these conditions hold:
*
    *
  • Modes map is not {@code null}/empty
  • *
  • Required mode setting is not {@code null}
  • *
  • The setting has a mapped value
  • *
  • The mapped value is a {@link Number}
  • *
  • The {@link Number#intValue()} is non-zero
  • *
* @see #getBooleanSettingValue(Object) */ public static boolean getBooleanSettingValue(Map modes, PtyMode m) { if ((m == null) || MapEntryUtils.isEmpty(modes)) { return false; } else { return getBooleanSettingValue(modes.get(m)); } } /** * @param modes The {@link Map} of {@link PtyMode}s resolved by the "pty-req" message. * @param enablers A {@link Collection} of enabler settings to be consulted * @param defaultValue The default value to be used if no definite setting could be deduced * @return {@code true} if the CR mode is enabled:
*
    *
  • Ifmodes or enablers are {@code null}/empty then defaultValue * is used
  • * *
  • If any of the enablers modes are enabled then the CR mode is enabled. *
  • * *
  • If none of the enablers modes were specified then use * defaultValue
  • * *
  • Otherwise (i.e., at least one or more of the enablers modes were specified, but * all of them said {@code no}) then {@code false}.
  • *
*/ public static boolean getBooleanSettingValue( Map modes, Collection enablers, boolean defaultValue) { if (MapEntryUtils.isEmpty(modes) || GenericUtils.isEmpty(enablers)) { return defaultValue; } int settingsCount = 0; for (PtyMode m : enablers) { Object v = modes.get(m); if (v == null) { continue; } settingsCount++; // if any setting says yes then use it if (getBooleanSettingValue(v)) { return true; } } // ALL (!) settings have said NO if (settingsCount > 0) { return false; } else { return defaultValue; // none of the settings has been found - assume default } } /** * @param v The value to be tested * @return {@code true} if all of these conditions hold:
*
    *
  • The mapped value is a {@link Number}
  • *
  • The {@link Number#intValue()} is non-zero
  • *
* @see #getBooleanSettingValue(int) */ public static boolean getBooleanSettingValue(Object v) { return (v instanceof Number) && getBooleanSettingValue(((Number) v).intValue()); } /** * @param v The setting value * @return {@code true} if value is non-zero */ public static boolean getBooleanSettingValue(int v) { return v != 0; } /** * @param m The {@link PtyMode} * @return {@code true} if not {@code null} and one of the settings that refers to a character value - name * usually starts with {@code Vxxx} */ public static boolean isCharSetting(PtyMode m) { if (m == null) { return false; } String name = m.name(); char ch = name.charAt(0); return (ch == 'v') || (ch == 'V'); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy