Заметки бессистемного программиста
13 subscribers
70 photos
112 links
Download Telegram
Захотел купить более удобное жало для паяльника, решил загуглить, что именно подразумевается под обозначением "900M-T-I" (запрос содержал конкретно эту строку без других слов), а гугл мне предложил помочь с математическими задачками (что бы под этим ни подразумевалось). Такой формат "быстрых ответов" я увидел впервые.
Из примера на cppreference:

class ThreadsafeCounter
{
mutable std::mutex m; // The "M&M rule": mutable and mutex go together
int data = 0;
// ...
}
🔥3
На Алиэкспрессе каталог каждого продавца может быть сгруппирован по категориям, и вот сразу у нескольких продавцов радиодеталей обнаружилась загадочная категория с названием "повел". В принципе, иногда даже "технические" аббревиатуры хорошо звучат, например, "мосфет", а уж "маркетинговый" термин тем более будет красивым. Хоть я и не планировал покупать загадочные по́велы, но интересно же, что так назвали — наверное, какую-нибудь мудрёную и современную микросхему, подающую питание на что-нибудь ещё более заковыристое и высокотехнологичное — ну, там, от power и electronics...

Почему-то в этой категории были просто какие-то светодиоды. Ну, думаю, может особый тип для каких-нибудь умных светодиодных лент... А потом до меня дошло: светодиод — это же грамматическая форма свинца: lead / led / LED. Ну а в названии категории потерялись точки над "ё".
2
Загадка: что может содержать файл с именем proton-pack.c в ядре Linux?
Ответ: противодействие уязвимостям типа Spectre 😀
Пояснение в комментарии в "шапке": "If there's something strange in your neighbourhood, who you gonna call?"
В копилку научного юмора и искусства в целом: Dance Your PhD 2025. Если обладатели главного приза кажутся слишком шумными, то вот, например, красивый спокойный клип про лазерное охлаждение атомов до сверхнизких температур что бы это ни значило :)
Обновил телефон (с Самсунга обратно на Моторолу и прекрасно себя чувствую), обновил ОС на телефоне. После обновления до Android 15 захотел поставить из F-Droid уже упоминавшийся на этом канале SatStat, да не тут то было: оказалось, что в Android 15 слишком старые приложения поставить нельзя (документация). Ну, то есть, не совсем так: во-первых, судя по всё той же странице документации, гайки начали закручивать ещё в Android 14. Во-вторых, поставить приложение всё же можно — с компьютера.

Итак, что я наблюдаю в F-Droid: плашка "Это приложение было разработано для старой версии Андроид..." (что пока ещё ничего не означает: у самого приложения F-Droid, через которое я смотрю каталог, в собственной карточке такая же плашка и ничего) и сказано, что совместимых с моим устройством версий нет. Кнопки "установить", соответственно, тоже. Проверяю предположение: из F-Droid на телефоне перекидываю через любой мессенджер ссылку на приложение себе же в браузер на компьютере. Из списка версий выбираю какую-нибудь посвежее, скачиваю APK-файл и пробую установить через ADB (добавлены переводы строк, чтобы не так сильно растягивать текст по горизонтали):
$ adb install /tmp/com.vonglasow.michael.satstat_30600.apk
Performing Streamed Install
adb: failed to install /tmp/com.vonglasow.michael.satstat_30600.apk:
Failure [INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target
at least SDK version 24, but found 23]

Ага, то самое изменение из Android 15. По совету из всё той же документации добавляю опцию --bypass-low-target-sdk-block:
$ adb install --bypass-low-target-sdk-block /tmp/com.vonglasow.michael.satstat_30600.apk
Performing Streamed Install
Success

Работает! Едва ли я бы хотел таким способом ставить что-то из Google Play — хотя бы потому, что не совсем понятно, откуда брать "эталонный" APK, который точно-точно без дополнительных троянов, да и при наличии альтернатив, возможно, стоит поискать какое-нибудь менее заброшенное приложение. Но к программам из репозитория* F-Droid лично у меня доверия больше, а правильный APK можно без лишних плясок с бубном скачать по удобной ссылке. В общем, опция удобная полезная, но использовать нужно на свой страх и риск: здесь никто за вас новому apk подпись не проверит.

* Почему важно уточнение именно о "репозитории" F-Droid — потому что существуют сторонние репозитории в том же формате, их так же можно добавлять в официальный клиент F-Droid, но это будут уже совершенно независимые, не контролируемые и не проверяемые авторами F-Droid источники ПО.

#android
Кстати, похоже, что в Андроиде есть разрешения, которые в принципе доступны и без рутования телефона, но выдаваться должны через ADB, а не обычный пользовательский интерфейс (тут, впрочем, нужно оговориться, что я совсем не Андроид-разработчик, и, например, не вполне уверен, что можно заявлять о неком стандартном интерфейсе управления правами, хотя в документации я и вижу достаточно чёткое разделение на normal, runtime a.k.a. dangerous permissions и ряд других типов).

Например, в репозитории F-Droid есть приложение LogFox, которое при первом запуске просит выдать права через ADB:
adb shell pm grant com.f0x1d.logfox android.permission.READ_LOGS

После чего при начале записи логов система переспросит уже на экране устройства, хотим ли мы позволить приложению читать "глобальные" логи. Если разрешили, можно видеть, например, такое:
libPowerHal: [setClusterFreq] system_server: sysfs_freq set cpu freq: 1750000 -1 1850000 -1

Или вот, например, SaverTuner: при первом запуске ждёт, пока ему не выдадут разрешение:
adb shell pm grant s1m.savertuner android.permission.WRITE_SECURE_SETTINGS

После чего позволяет выбирать один из нескольких профилей экономии, а внутри профиля — переключать большое количество параметров из серии "разрешить анимации", "отложить полное резервное копирование" и т.д.

Лично я для себя пока не нашёл "полезный в быту" пермишн и приложение, его использующее, но сам факт существования таких разрешений кажется мне полезным знанием.

#android
Первого апреля я уже хвастался колпачком для разъёма XT60, отлитым из термоклея. И вот недавно история получила не менее первоапрельское продолжение... Как я уже говорил, столь суровый разъём требовался, чтобы подключить одноплатник, питающийся от пяти вольт, без значительного падения напряжения на разъёме, потому что со штекерами-бочонками я к тому моменту уже намучился. Но кроме одноплатника линии 5 и 12 вольт шли ещё и на "метеостанцию" на ESPHome, роутер и ethernet-свич, поэтому мешанина проводов была та ещё. Я захотел хоть как-то это смотать и убрать в обычную электромонтажную распределительную коробку, а чтобы упростить себе перекоммутацию в стеснённых условиях, повесить эту коробку на край столешницы при помощи примерно таких крючков с Алиэкспресса.

Начитавшись отзывов, мол, "крючки хорошие, но мне пришли без липучек", осмотрел то, что прислали мне. С грустью отметил, что у меня тоже просто крючки, и стал лепить на двусторонний скотч. А они, заразы, ещё и как из вредности к скотчу не липнут... Ладно, к распределительной коробке с горем пополам прилепил на термоклей (который, разумеется, тоже отваливался, но я упорный, я через край чисто механически прихватил, а потом долго подрезал ножом, чтобы нигде не клинило...). Но не буду же я к столу ответную часть тоже на термоклей лепить... Тут я вспомнил про сантехнический скотч, решил сделать из него кольцо клеевой стороной наружу и хоть как-то уже прилепить ответную часть крючка.

Отклеил от мотка скотча небольшой участок, приложил туда крючок... а он отваливается!!! Да вы что, издеваетесь, что же это за крючки такие, что их даже чудо-скотч не берёт?!? И тут-то я пригляделся и заметил, что на скотче осталась прозрачная плёночка... 🤦‍♂️ В общем, всё нормально: честь сантехнического скотча восстановлена, а я усвоил урок, что если тебе кажется, что некая поверхность отваливается от двустороннего скотча, термоклея и прочих нормальных липучек, словно специально спроектирована, чтобы легко отваливаться от любого клея, то возможно, тебе не кажется. После снятия защитной плёнки "предустановленный" клеевой слой крючка благополучно прилип, куда следовало.
Недавно я решил приобщиться к современным технологиям и обновить свой роутер до чего-нибудь на AArch64 (64-битном ARM) вместо MIPS, и с поддержкой нового wi-fi стандарта "ax". Как оказалось, относительно недорогие устройства в продаже есть, в том числе и с критичной для меня возможностью поставить OpenWRT, но почти у всех 4 ethernet-порта, а не 5, как было на моих прошлых роутерах. Это проблема: один порт WAN, ещё два — мой настольный компьютер и провод к powerline-адаптеру, ещё один — на торрентораздавалку, а хочется иметь запасной порт "на мелкие расходы": временно какой-нибудь raspberry pi подключить для настройки, например.

Требований к устройству у меня было и без того немало, а критерий наличия 5+ ethernet-портов портил картину окончательно. В общем, небольшой лайфхак: вычеркнуть из списка требований количество портов (ну, на самом деле, снизить его до безобидных 3+) поможет неуправляемый ethernet-коммутатор — что-то вроде вот такого устройства. Подобный коммутатор — штука довольно простая, не требующая и, как минимум в моём случае, даже не допускающая настройки: просто воткнул сетевые кабели, подал питание, и через мгновение она уже пуляет входящие ethernet-фреймы в те порты, где последний раз видели нужный MAC-адрес — никаких тебе линуксов, веб-интерфейсов настройки и долгой загрузки при включении. В итоге требование на минимальное количество ethernet-портов роутера снизилось до 3, то есть количества зон файрвола: WAN, LAN и "публично доступные серверы". Правда, потребуется запитать ещё одно устройство от розетки — для меня это, к счастью, оказался пройденный этап, но это уже совсем другая история...
👍1
В только что лет уяснил для себя очевидный "опосля" факт: понадобилось купить монитор, и по такому случаю решил проэкспериментировать, и вместо 24" 1080p@60Hz купить 27" 1440p@100Hz (увеличение диагонали — не самоцель, просто достаточно бюджетных 24" с такими параметрами я не нашёл, а так бы только рад был ещё большей плотности пикселей).

Иногда в обсуждениях мониторов с большими диагоналями или частотами обновления я видел сетования на то, что придётся на новую видеокарту раскошеливаться, но проходил мимо с мыслями: "Ну мне-то не для игр, мне чтобы за целый день от глядения в текст глаза не уставали, а с отрисовкой интерфейсов даже встроенный видеочип всегда справлялся без вопросов". В итоге принёс монитор, подключил — и фигушки: нативное разрешение 2560x1440 завелось без проблем, но на 60Hz. Загуглил, и оказалось, что через имеющийся на моей системной плате видеовыход HDMI версии 1.4 можно прокачать только 8.16 Gbit/s несжатых видеоданных, а значит 2560x1440x100x24 ну никак не пролезет. Кстати, по быстрым прикидкам должно бы пролезать аж 92Hz, но Википедия пишет про 85Hz — видимо, накладные расходы на "поля" вокруг видимой области или просто 85Hz — это частота, которая "ну хоть сколько-то стандартная в отличие от".

Почему с нативным разрешением не завелось, скажем, на 75Hz — не знаю, почему-то в EDID монитора такой режим не прописан. Буду разбираться, но это явно выглядит не столь неожиданным осознанием, как то, что я, человек далёкий от AAA-игр, столь запросто умудрился упереться в ограничение интерфейса HDMI.
🤔1
Линуксоидное воспоминание из школьных времён, или что бывает, когда не слушают мудрые советы и парсят вывод ls.

Пункт первый: однажды я узнал, что у команды ls (если точнее, то у той её реализации, что "в линуксе", то есть из GNU coreutils, но тогда я, наверное, о таких деталях не задумывался) есть параметр --color[=WHEN], принимающий одно из трёх значений: never, auto и always (при этом "always" подразумевается по умолчанию, если передан просто --color). С этим параметром каталоги будут печататься одним цветом, архивы — другим, текстовые файлы — третьим... Недолго думая, прописал себе на постоянной основе в .bash_profile
alias ls="ls --color"

Изучать, чем отличаются опции auto и always — зачем?..

Пункт второй: я захотел написать shell-скрипт, который пройдёт по списку файлов в каталоге и для каждого создаст ещё какой-то файл с "производным" именем. Ну, что-то вроде "был file.c — создадим file.c.backup1". Сейчас по запросу don't parse ls гугл выдаёт довольно много всего — наверное, выдавал и тогда, но я же был не какой-то зануда, соблюдающий best practices, я выяснял, как сохранить вывод ls в переменную и разобрать его на части.

Пункт третий: решив посмотреть, что же мой скрипт нагенерировал, я с удивлением обнаружил, что теперь цвет намертво въелся в имена свежесозданных файлов — хоть ты с --color=always печатай, хоть с never...

Сейчас, правда, coreutils поумнели, и попытка напечатать "раскрашенное" имя сразу выдаёт неладное, но всё-таки воспроизвести фокус труда не составляет. А разгадка — когда-нибудь в следующих сериях.
Заметки бессистемного программиста
Линуксоидное воспоминание из школьных времён, или что бывает, когда не слушают мудрые советы и парсят вывод ls. Пункт первый: однажды я узнал, что у команды ls (если точнее, то у той её реализации, что "в линуксе", то есть из GNU coreutils, но тогда я, наверное…
Итак, пришло время собраться с мыслями и доработать черновик от 7 сентября (первым делом выкинув вступление про "не откладывая в долгий ящик", ага). На самом деле, угадайку я не планировал — просто не был готов описать всё за один присест. За один месяц, как оказалось, тоже ;)

Откуда же взялась возможность "раскрашивать" имена файлов? Дело в том, как в юниксовой консоли описывается форматирование выводимого текста: большинство атрибутов и команд идут в том же потоке байтов, что и сам текст — такое вот подобие языков разметки. Вероятно, это как-то связано с тем фактом, что раньше терминалы были отдельными железками, подключаемыми к мейнфрейму ограниченным количеством проводов, и нельзя было просто сказать "хочешь переместить курсор — дёрни прерывание, оно обновит неуточнённые структуры данных в памяти, потом как-нибудь нарисуем". А в "однокомпьютерном" DOS так сделать было можно, поэтому вроде бы даже в Винде до недавнего времени форматирование текста в консоли делалось через некие вызовы WinAPI. Впрочем, тут меня уже понесло в сторону домыслов. Что же, попробую кратенько изложить структуру типичных escape-последовательностей, авось в процессе и сам наконец-то разберусь, почему зелёный цвет — это ^[[32m :)

Насколько я понял, важной вехой в терминалостроении стал VT100 и его вариации — это был один из первых терминалов, поддержавший унифицированный стандарт управляющих последовательностей: ANSI escape codes, которые были задуманы в качестве замены туче несовместимых фирменных систем кодов у каждого производителя. На самом деле, довольно интересно читать описание этой железки: восьмибитный процессор Intel 8080, возможность докупить платы расширения — прямо отдельная персоналка (ну... восьмибитная — так 1978 год на дворе) для общения большой машины с пользователем. Впоследствии ANSI-коды оказались в той или иной мере поддержаны во многих эмуляторах терминалов — видимо поэтому, несмотря на существование утилиты tput для вывода правильных последовательностей для конкретного терминала, я тем не менее вижу захардкоженные коды в убунтовском .bashrc для раскрашивания приглашения командной строки.

Для начала поймём, что такое ^[. На самом деле все эти ^C, ^H и прочие — это не просто жаргонное обозначение для сочетаний Ctrl+<буква>, а так называемые Caret notation: ^A — это control-code 1 (фактически, просто символ с кодом 0x01), ^C — control-code 3, ^Z — control-code 26, а control codes с последующими номерами используют символы, идущие в таблице ASCII после заглавных букв: следом за Z идёт как раз [, то есть ^[ — это control-code 27, он же символ с кодом 0x1b, он же ESC. Тут ещё отдельный вопрос: ^[ и caret notation — это, конечно, замечательно, но ни printf в C, ни правила экранирования строк в bash этого не поймут. Поэтому пока предлагаю остановиться на конкретном способе выводить такие символы: shell-команде printf, довольно сильно мимикрирующей под одноимённую функцию языка C. Команда printf так же принимает "строку формата" своим первым аргументом, и в ней ^[ можно описать как \e.
С caret notation разобрались, теперь допишем оставшийся n-1 символ. Последовательности, начинающиеся с \e[ (то есть двух байтов: ESC и всамделишного [), являются частным случаем Fe escape sequences. После префикса из двух байтов ESC и [ в общем случае идёт сначала ноль и более "байтов-параметров", потом ноль и более "промежуточных байтов", а следом — ровно один "финальный байт". И "параметры" и "промежуточные" байты принадлежат алфавитам из 16 символов: байты-параметры имеют коды 0x30-0x3F (цифры 0-9 и ещё шесть "спецсимволов", следующих за ними в таблице: :;<=>?), но обычно представляют собой последовательность десятичных чисел, разделённых точкой с запятой, а промежуточные байты — 0x20-0x2F (!"#$%&'()*+,-./ — сплошные "спецсимволы"). Ассортимент финальных байтов гораздо богаче: этот байт должен иметь код из диапазона 0x40-0x7E, что включает в себя все заглавные и строчные буквы, плюс 11 "спецсимволов" (а вот непечатный символ DEL с кодом 0x7F не включает — упражнение на внимательность).

Посмотрим теперь на конкретный пример: вывод ls. Чтобы увидеть, какие байты печатаются в терминал, перенаправим вывод команды на вход утилиты hd, которая выдаст три колонки: смещение от начала файла (или, как у нас, потока байтов), строчку из 16 байтов в шестнадцатеричном виде и те же байты, но текстом (заменяя непечатные символы на точку). Для начала поймём, как будет выглядеть обычный текст без "украшений":
$ echo ABCA | hd
00000000 41 42 43 41 0a |ABCA.|
00000005

Мы видим символы "A", "B", "C" (с кодами 0x41, 0x42 и 0x43, соответственно), потом опять "A", а после — перевод строки (код 0x0a).

Теперь попробуем перейти в пустой каталог, создать в нём подкаталог с именем ABCA и "увидеть" его при помощи ls:
$ ls --color=never | hd
00000000 41 42 43 41 0a |ABCA.|
00000005
$ ls --color=always | hd
00000000 1b 5b 30 6d 1b 5b 30 31 3b 33 34 6d 41 42 43 41 |.[0m.[01;34mABCA|
00000010 1b 5b 30 6d 0a |.[0m.|
00000015

Скучный, "чёрно-белый" ls просто напечатал уже привычные четыре буквы и перевод строки, а вот в "цветном" варианте размахнулся аж на 21 байт, где не сразу и заметишь наш знакомый маркер "41 42 43 41" и перевод строки "0a". Оставшиеся 16 байт — это последовательности Select Graphic Rendition: сначала двухбайтный префикс \e[, потом последовательность чисел-команд через точку с запятой и завершающая буква m:
* \e[0m (4 байта, команда 0) — сбросить все атрибуты (reset or normal)
* \e[01;34m (8 байтов, команды 1 и 34) — поярче (bold or increased intensity) и синим текстом (blue foreground)
* ABCA (4 байта) — собственно, само имя каталога
* \e[0m (4 байта, команда 0) — прибираем рабочее место, опять сброс
* \n (1 байт) — перевод строки

Такую же последовательность байт (с таким же эффектом) можно самостоятельно выдать в терминал командой
printf '\e[0m\e[01;34mABCA\e[0m\n'
Мелочь, а удобно. Иногда нужно зайти по SSH на удалённую систему и скачать там что-нибудь из интернета. Обычно в таких случаях я просто переходил в каталог, куда нужно скачать файл, командовал wget https://example.org/path/to/file.tar.gz и радовался. Правда, иногда вместо wget был только curl — тогда радовался я чуть меньше, потому что нужно было вспомнить минимальный набор опций: что-то вроде -L, чтобы идти, куда послали обрабатывать перенаправления в HTTP и -O, чтобы просто сохранить файл под ожидаемым именем file.tar.gz.

Однажды скачиваемый файл оказался не просто file.tar.gz, а file-1.tar.gz, file-2.tar.gz, ..., file-20.tar.gz (а там ведь и весь остальной URL https://example.org/path/... к каждому приписан) — получается очень длинная командная строка, и запросто можно запутаться и что-нибудь пропустить. Тут-то обнаружилась оборотная сторона курловых хитростей: можно просто написать (обратите внимание на одиночные кавычки)
curl -L -O 'https://example.org/path/to/file-[1-20].tar.gz'

и curl сам разберётся со счётчиком, и скачает все 20 файлов один за другим. Кавычки нужны не для curl (он их как раз не увидит), а чтобы bash (думаю, ровно то же применимо и к zsh) даже не пытался сам раскрывать шаблоны с квадратными скобками, а просто достал содержимое из одиночных кавычек, и передал как ровно один аргумент запускаемой программе. Кроме приведённого выше примера у curl есть ещё несколько аналогичных вариантов раскрытия одного урла в последовательность — они удобно указаны прямо в начале man-страницы.
А вот ещё одна байка на стыке двух предыдущих тем, но совсем свежая: о том, как я решил сохранить локально подборку iso-образов с исходниками Debian (суммарно около 90 гигов). И в тот момент мне показалось логичным (наверное, это нифига не логично, но тогда показалось), что торренты торрентами, пусть файлы не валяются без дела, а раздаются, но вот скачать не столь популярные образы будет эффективнее по HTTP с географически близкого зеркала, вот прям curl-ом, ага, такой вот принудительный web seed.

Поскольку любым способом качать пришлось бы долго, запустил команду наподобие такой
nohup curl --limit-rate 3M -L -O 'https://...-source-DVD-[1-20].iso' &


с помощью стандартной утилиты nohup обезопасив curl от завершения вместе с командной оболочкой при отключении от ssh. Важно, что при этом утилита nohup перенаправляет вывод программы в файл nohup.out в текущем каталоге.

И вот я запустил загрузку, потом периодически смотрел прогресс и видел там отчёты вроде
# cat nohup.out
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4476M 100 4476M 0 0 3075k 0 0:24:50 0:24:50 --:--:-- 3078k
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4481M 100 4481M 0 0 3075k 0 0:24:51 0:24:51 --:--:-- 3073k
...

Вывод прямо, как "в прямом эфире", только последняя строчка (текущий загружаемый файл) не обновляется каждую секунду, ведь это всего лишь напечатанный в терминал файл, каким он был на момент печати. Ещё удивлялся, какой curl умный: проверил, что дескрипторы stdout/stderr указывают на обычный файл (с помощью isatty что ли?..) и стал аккуратно позиционироваться в nohup.out, обновлять строчку текущей загрузки, никакой тебе мешанины, как у некоторых, когда на каждую десятую процента выводится новая строка...

Секрет фокуса оказался в том, что фокус мне никто не показывал и даже не собирался: файл на полсотни отображаемых строк весил мегабайт с лишним. Оказывается, curl просто печатал форматированный вывод в выходной поток, не смотря ни на что, прямо со всеми "вернись к началу строки и напиши заново" каждую секунду. Когда же я в очередной раз выполнял cat nohup.out, мегабайт текста вперемешку с escape-последовательностями в очередной раз оказывался отправлен по SSH в "программу-терминал" (или, говоря корректнее, эмулятор терминала) на "большой компьютер", которая в очередной раз интерпретировала мегабайтный вывод курла, отображая в конечном итоге полсотни строк текста. Теперь мне уже интересно, почему НЕ все программы ведут себя столь же прозрачно, и могут формировать много повторяющихся строк при перенаправлении вывода. Наверное, они пытаются поступать правильно и работать с произвольным терминалом через какой-нибудь ncurses, а не захардкоженные ANSI escape sequences, и получив от библиотеки ответ, что это не терминал, а вообще непойми что, сами откатывались на "некрасивый" формат вывода.
Последнее время я начал присматриваться, как вообще можно подступиться к использованию нейросетей в быту, но, разумеется так, чтобы локальный запуск, безопасность, все дела... Так вот, один из известных "производителей" LLM, пригодных для локального инференса — французская Mistral AI, но, конечно, пообщаться с её нейронками можно и в облаке при помощи продукта под названием le Chat. И меня веселит это название, поскольку в школе я сначала изучал французский, и до сих пор помню, что "le chat" — это "кот" (произносится как "лё ша"). В общем, начитавшись новостей о всех этих новомодных тайминг-атаках на кэш процессора и историй о переполнении буфера в firmware сетевой карты, я уже давно ценю замечательное изречение: "Паранойя — это не когда разговариваешь только со своим котом, паранойя — это когда при коте боишься сболтнуть лишнего". А тут оно прямо заиграло новыми красками.
Знаете ли вы?
... что среди RFC-документов, описывающих многие важные стандарты, существует RFC 2119, определяющий смысл терминов MUST (NOT) / SHOULD (NOT) / MAY, используемых в других документах. Более того, есть также RFC 8174, разъясняющий, что RFC 2119 относится только к терминам, написанным заглавными буквами, а остальные слова подчиняются обычным правилам английского языка.

Последующие документы просто ссылаются на эти разъяснения:
1.1. Conventions Used in This Document

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

...