Блог
Адреса овог блога на мојој Џемини капсули: gemini://gemini.strahinja.org/blog
-
2023-04
База из командне линије
26.04.2023Радећи на мом „day job“ у школи, већ низ година користим разне системе за вођење евиденције. Временом сам тако дошао до самих основа, које су више него довољне за већину примена које су потребне „обичним смртницима“. То решење, које користи TSV табеле као основни начин складиштења података, сам описао у новом тексту под насловом „База из командне линије“.
-
2023-03
Слагалица
23.03.2023Прегледајући своје старе програме, подсетио сам се аплета у Јави који сам написао 2009. године. Ради се о демонстрацији идеје о томе шта се стварно збива у квизу „Слагалица“ у игри састављања најдуже речи. Наиме, мој отац је сматрао да у тој игри не долази ни до какве „претраге“ списка речи, нити до састављања најдуже речи од стране организатора на лицу места, већ се реч унапред задаје, а све остало су обичне анимације. На тај начин се могу објаснити и ситуације у којима учесници пуким случајем добију дужу реч од организатора.
Док сам тражио начин да покренем тај стари аплет, суочио сам се са тим да то у најновијој верзији Јаве, OpenJDK 17, једноставно није могуће. Читав концепт аплета је, како сам сада сазнао, још 2017. напросто означен као застарео (deprecated) и избрисан из Јаве!
Зато сам направио еквивалент тог аплета у JavaScript‑у. Његова функционалност је отприлике иста.
config.h и redo
12.03.2023Ко је радио са suckless програмима сигурно зна да се они подешавају изменом заглавља config.h. На пример, комбинације тастера се у програму dwm задају преко низа
keys[]
:static const Key keys[] = { /* modifier key function argument */ { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, /* итд. */
У suckless програмима, иницијално се датотека са подешавањима добија копирањем датотеке config.def.h, која служи као шаблон. Датотека config.h се на крају укључи из изворног кода, па он може директно да користи дефиниције подешавања.
Ова конвенција није природна за систем за изградњу redo. Да би се представило копирање датотеке config.def.h у датотеку config.h, потребно је да redo датотеку config.h забележи као тзв. „генерисану датотеку“. Међутим, чим је корисник измени, она то престаје да буде. Уколико се потом покрене redo, он ће се жалити:
redo: config.h - you modified it; skipping
и увек ће сматрати да одредишта која зависе од ње морају да се наново изграде. Ово не ствара никакав проблем у погледу крајњег резултата, али је сувишно и представља непотребно губљење ресурса.
Једино решење које за сада видим као сврсисходно је да се уведе „посредник“, датотека _config.h, која би била генерисана копирањем датотеке config.h сваки пут када се покрене redo, и којој би се затим одредио статус „свежине“ наредбама
redo-always redo-stamp <$3
Овај систем сам тренутно применио у мојим програмима који користе redo.
Додатак 2023-03-15: Током дискусије на redo групи, сазнао сам за постојање наредбе redo-ifcreate, која се може употребити уместо идиома redo-always+redo-stamp да се посредничка датотека _config.h изграђује само када се измени config.h, па сам на крају применио то решење.
-
2022-09
DDoS ажурирањем
20.09.2022Недавна дискусија на Sourcehut‑овој мејлинг листи ми је скренула пажњу на чланак са блога Друа Деволта, аутора Sourcehut‑а, иначе ватреног поборника језика Go, у ком он описује навалу захтева на git.sr.ht од стране Go компајлера.
Мој коментар је да ово конкретним и врло пластичним примером истиче потенцијалне недостатке језика који користе систем пакета. Поред Go‑а, у овакве језике спадaју многи данас популарни и на сва звона хваљени језици, као што су JavaScript са npm‑ом, Python, Rust и слични. Све мора да буде „always online“: почевши од оперативног система, преко игрица, па до алата за програмирање. Интернет се непотребно оптерећује гомилом непотребних података. Уместо правилног offline модела програмирања, сада „пакети“ функционалности програмског језика увек морају бити ажурни.
Ово нас доводи до суштине, а то је приватност. Да би се пакети „освежили“, неопходни су захтеви централном серверу (у случају Go‑а: Гуглу), а излишно је истицати да то у преводу значи праћење корисника, тј. блатантно нарушавање приватности још једним извором информација за Гуглове механизме социјалног инжењеринга.
Они који бране модерне програмске језике обично су веома фанатични. Макар и наговештај критичности према Go‑у или Rust‑у наилази на жестоку осуду саговорника. Насупрот овоме, ја сматрам да би закључак сваког ко посматра „модерне“ програмске језике без предрасуда требало да буде одлучно „не“ таквом моделу програмирања. Уместо што очекују да сам програмски језик надокнади недостатак њиховог знања и искуства или једноставно лењост, „програмери“ би требало да науче да правилно управљају меморијом и програмирају уместо да кодирају. Лењост је већ тежа за искоренити.
-
2022-08
Важност прототипова
31.08.2022Радећи на писању mkfile‑а за Neomutt, сусрео сам се са необичним проблемом. При покретању, Neomutt је крахирао уз SIGSEGV, а испитивањем у GDB-у установио сам да до грешке долази у фајлу gui/terminal.c, у линијама 62-63:
char *tcaps = tigetstr("tsl"); if (tcaps && (tcaps != (char *) -1) && *tcaps)
Наиме, вредност показивача
tcaps
је у моменту segmentation fault‑а0xfffffffff75de85c
, што није адреса којој програми смеју приступати. Даље испитивање ме је довело до функцијеtigetstr(3)
из NetBSD-curses‑а:const char * ti_getstr(const TERMINAL *term, const char *id) { ssize_t ind; size_t i; TERMUSERDEF *ud; _DIAGASSERT(term != NULL); _DIAGASSERT(id != NULL); ind = _ti_strindex(id); if (ind != -1) return term->strs[ind]; // <-- ово се враћа... /* ... */ } char * tigetstr(const char *id) { _DIAGASSERT(id != NULL); if (cur_term != NULL) { char* ret = ti_getstr(cur_term, id); return __UNCONST(ret); // <-- ... и прослеђује // макроу __UNCONST } return (char *)CANCELLED_STRING; }
Адреса показивача
term->strs[ind]
који се враћа из интерне функцијеti_getstr
у функцијуtigetstr
je0x7ffff75de85c
, што је исправна адреса показивача, и у GDB‑у се приказује као знаковна ниска. Она се после cast‑овања макроом__UNCONST
:#define __UNCONST(a) (void *)(intptr_t)(a)
враћа и додељује већ поменутом показивачу
tcaps
у функцијиmutt_ts_capability
у Neomutt‑у.Међутим, ту долази до проблема:
0x7ffff75de85c
одједном постаје0xfffffffff75de85c
. Зашто?Испрва сам помислио да је кривац различита врста кода у односу на позицију (PIC - Position Independent Code), али поновно компајлирање NetBSD-curses‑а и Neomutt‑а уз
-fPIC
није ништа променило.Затим сам покушао да направим мали тест програм, који би иницијализовао NetBSD-curses и позвао проблематичну функцију
tigetstr
. На моје изненађење, док је Neomutt проузроковао segmentation fault, тест програм је радио без проблема! Додавање још кода из Neomutt‑а тест програму није променило ситуацију.Оно што ми је коначно дало идеју шта је узрок проблема је следећи одговор на питање на StackOverflow‑у:
-
channelGet()
is assumed to returnint
(due to lack of prototype) [истакао СР], so the result is truncated to0xf7fed1a0
- then it is cast to a 64-bit pointer, so gets sign-extended to
0xfffffffff7fed1a0
„Претпоставља се да функција враћа
int
, због недостатка прототипа, па је резултат скраћен. Онда се cast‑ује у 64‑битни показивач, коме се продужава знак.“ Па наравно, недостатак прототипа! Функцијаtigetstr
захтева укључивање заглавља term.h, које није било укључено са том путањом, већ као ncurses/term.h. Што се тиче самог прототипа, у овом случају он је сасвим једноставан, без struct‑ова, али је његов недостатак ипак проузроковао SIGSEGV!
Епилог: Neomutt ипак захтева функције које недостају NetBSD-curses‑у, па ћу за његово коришћење по свој прилици морати или да их сам напишем, или да пређем на гломазни ncurses, али сам из целе ствари имао прилике да научим нешто ново.
Галеб 2.0
15.08.2022Јуче сам одлучио да објавим репозиторијуме дистрибуције Галеб, а објавио сам и њену веб страницу у оквиру моје странице на SourceHut-у. Тренутно је функционална основа система, односно клонирањем репозиторијума
$ git clone https://git.sr.ht/~strahinja/galeb
штеловањем скрипта
lib/env.sh
и покретањем скриптова01-*
до05-*
добија се инсталација система у директоријуму$GR
(подразумевано$HOME/galeb-root
). Ту инсталацију скриптови rsync-ом копирају у бут слику компресовану xz-ом. За више детаља се може погледати страница INSTALL.У наредном периоду намеравам да додајем нове пакете у виду mkfile-ова у репозиторијуму
galeb-mkfiles
.mkpk
06.08.2022Најновији део дистрибуције Галеб, на којој радим последња два месеца, је систем за управљање пакетима mkpk. Његова основна идеја је слична идеји система mkbuild Хилтја Постхуме — систем за изградњу ОС‑а Plan9 под називом mk се користи за изградњу пакета из изворног кода. mkfile‑ови потребни за изградњу свих пакета који се користе у Галебу се налазе у једном репозиторијуму, и њиховом употребом је избегнут autoconf. Они су директно прилагођени изградњи конкретног пакета за Галеб.
Типична употреба mkpk‑а за, рецимо, изградњу и инсталирање текстуалног Gopher клијента sacc би била:
# mkpk update # опционо; преузима најсвежије верзије mkfile-ова # mkpk fetch sacc # преузима потребне архиве изворног кода и смешта их у # директоријум /src/pkg # mkpk build sacc # изграђује sacc-[верзија].{tar.xz,sha512} и смешта их у # директоријум /pkg # mkpk install sacc # инсталира добијену архиву простим распакивањем у /
Информација о инсталираним пакетима се чува у датотеци
/pkg/pkgdb.tsv
, која је обична датотека у формату TSV. Ово знатно олакшава преглед и манипулацију тим информацијама. Рецимо, може се употребити мој програм table за приказ података о свим инсталираним пакетима:$ tsvtable /pkg/pkgdb.tsv
или се може употребити grep за издвајање само информација о појединачном пакету:
$ grep "$(printf '^sacc\t')" /pkg/pkgdb.tsv sacc 1.06-10-gb567fed 2022-08-06 18:38
Ово би требало да је једна од последњих етапа пре него што коначно отворим репозиторијум Галеба за јавност, наравно ако се изузме писање великог броја mkfile‑ова за све пакете који ће ући у његов састав. Ипак, сада се већ назире тај тренутак.
-
-
2022-07
sinit
19.07.2022Наставио сам рад на дистрибуцији Галеб, која у текућој верзији може да се бутује у текстуалну конзолу (tty), и заснована је на програмима из колекција sbase, ubase и 9base. За сада Галеб 2.0 има, између осталог, следеће програме: sdhcp, smdev, tmux, GCC, git, vis, sled, curl, mksh, „one true“ awk, dcron, Perl, Python 3, groff, metalog, efibootmgr, mandoc, итд. Највише времена ми тренутно узима прилагођавање suckless (условно речено) „супервизора процеса“ svc, који је суштински на upstream‑у у алфа верзији. Мени лично је то изазов да надоградим svc до нечега што би могло да обезбеђује макар основну функционалност осталих супервизора процеса а истовремено да не буде превише компликовано.
Како изгледа моја прилагођена верзија svc‑а може се видети на слици. Такође сам изменио и suckless getty тако да приказује /etc/issue.
Бутовање Галеба 2.0 У мојој верзији svc‑а команде svc и service су равноправне, али је service више „пријатељска према кориснику“, са ANSI шаренишем, а svc је аскетска, у стилу Уникс алата. На слици се може видети употреба команде service:
Контрола сервиса у Галебу 2.0 Иста функционалност, изузев исписа, се постиже наредбама
# svc -s sdhcp # svc -r sdhcp # svc -e sdhcp # svc -k sdhcp
итд. Ове наредбе се једино разликују по томе што им је повратни код (
$?
) једини фидбек у случају да је све протекло без проблема.Иако бих већ сада могао да отворим репозиторијум Галеба за јавност, ипак ћу сачекати док он не буде заокружен у једну почетну целину. Тренутно разматрам додавање X.Org‑а, који је, нажалост, сам по себи пренатрпан (bloated) преко сваке мере, чак и у најогољенијој варијанти која би била довољна за покретање графичких suckless програма као што су dwm и st. Идеално би постојало засебно окружење које не би зависило од терета година традиције компатибилности са стандардима и претходним верзијама, али које не би било ни претрпано и хаотично као што су то Wayland или Arcan. Анселм Гарбе је својевремено имао сличну добру идеју, која нажалост није одмакла даље од грубе скице.
-
2022-06
Галеб
16.06.2022Завршио сам прву етапу у развоју сопствене дистрибуције musl/GNU/Linux‑а, коју сам назвао Галеб. Оно што се може видети на слици је прилагођена верзија Musl‑LFS‑а, која тренутно може да се похвали заузећем око 30 МБ меморије са улогованим једним корисником (рачунато према алгоритму програма free(1), односно
укупно - слободно - бафери - кеш
):Галеб 1.0 у емулатору QEMU Тренутно овај систем има функционални мрежни интерфејс (уз DHCP преко dhcpcd(1)‑а), git, GCC 12.1.0, curl итд.
Ипак, ово је тек почетак, зато што нисам задовољан низом карактеристика Musl‑LFS‑а, пре свега основном идејом. Она подразумева „обичан“ GNU/Linux систем, који само уместо glibc‑а користи musl‑libc (и, наравно, уместо systemd‑а користи s6). За разлику од овога, ја ћу покушати да постепено дођем до система који ће користити sinit, и бити што ближи stali‑ју (уз одређене компромисе као што је mksh; динамички линковани програми иду у /sucks).
Са тим у вези, вреди поменути glaucus, пројекат сличних амбиција, али који је по мом мишљењу завршио превише близу Musl‑LFS‑у. Његова документација садржи причу о процесу који је његов аутор прошао у потрази за „светим Гралом“ минимализма. Ипак, констатација из његове документације:
i.9. What Is glaucus Now?
glaucus in its current state is a bunch of shell scripts written in POSIX DASH, that build a musl libc and toybox based Linux® distribution from scratch.више није актуелна, зато што glaucus‑ов репозиторијум уместо „shell скриптова у POSIX dash‑у“ садржи Rust програм. Толико о његовој „једноставности“.
Статичка једноставност
07.06.2022Већ дуго година имам идеју о томе да направим сопствену дистрибуцију ГНУ-а са Линуксом. Linux From Scratch ми је познат још од периода када сам први пут почео да се бавим овим системом, а пре неколико месеци сам први пут у QEMU виртуелној машини изградио сопствени Linux From Scratch систем. Како ми је тренутно циљ да направим систем који ће бити превасходно статички линкован уз што мање сувишног, ових дана експериментишем са варијантом LFS-а, Musl-LFS.
Основне идеје система који желим да направим су сличне идејама дистрибуције stali:
За сада сам успео да направим основу система, која је базирана на делу Musl-LFS-а, али у наредним итерацијама намеравам да пређем на нешто што би било ближе овим основним идејама.
$ ls -lh /bin/mksh -r-xr-xr-x 1 root root 500K Jun 6 21:02 /bin/mksh $ file /bin/mksh /bin/mksh: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
-
2022-05
Тачка на Artix
20.05.2022После око 8 месеци, одлучио сам да напустим место 66 maintainer‑а за Artix Linux. Разлог је за мене сасвим неочекиван, а само ћу рећи да се ради о веома контроверзним ставовима естаблишмента Artix Linux-а, који су непознати широј јавности и вероватно би били једнако изненађујући када би били објављени, а свакако би били порицани.
-
2022-02
sled
15.02.2022 -
2022-01
Освежавање GPG кључева, други део
19.01.2022Јуче сам обновио један од GPG кључева који користим за потписивање мејлова и повукао стари кључ. После мало детаљнијег проучавања разних текстова о року трајања GPG кључева, одлучио сам да убудуће само продужавам време истека поткључева, уместо да повлачим целе кључеве. Такође, планирам да користим посебне поткључеве за потписивање, уместо потписивања примарним кључевима.
Midnight ¢ommander
12.01.2022Пошто сам прошле године започео ажурирање превода програма на српски, следећи на листи је био GNU Midnight Commander, или, у духу идеје превода коју сам пре много година осмислио и делио са другим преводиоцима софтвера на српски, ГНУ-ов Поноћни наредник. Међутим, на сајту Midnight Commander-а поводом помоћи у превођењу пише ово:
We have an account on the Transifex project. If you want help us with translations - just sign in (or log in) on the Transifex and do it :).
Испоставља се да је за допринос превођењу GNU Midnight Commander-а на српски неопходно креирати налог на онлајн сервису за превођење „Transifex“, који се по истеку „пробног периода“ од 15 дана плаћа, и (наравно) садржи „политику приватности“ која открива колико личних података Transifex тврди да узима од потенцијалних преводилаца.
Заиста? Да бих преводио слободни софтвер на неки други језик морам да платим? Некада се овако нешто нипошто не би могло очекивати од програма који у свом имену садржи префикс GNU. Даљим истраживањем открио сам да у време када је донета одлука да се пређе на Transifex, тај сервис није наплаћивао креирање налога, што се може видети у дискусији у архиви мејлинг листе mc-devel. Међутим, сада се види зашто је то била лоша одлука, која се из овог или оног разлога не преиспитује.
Пошто одбијам да користим услуге приватних фирми које се наплаћују новцем и личним подацима да бих приложио допуну локализације програма који је слободни софтвер (апсурд!), намеравам да то ажурирање локализације mc-а на српски урадим локално и понудим као pull request на GitHub-у. Ако желе то ажурирање превода, одлично, а ако не, то ће само допунити лошу слику о садашњем стању пројекта GNU MC.
-
2021-11
Освежење превода ELinks-а
25.11.2021Данас сам ажурирао превод текстуалног веб читача ELinks. Последњи пут сам радио на том преводу сада већ далеке 2005, пре 16 година.
Током година се много тога променило, и у вези са ELinks-ом и уопште. Идеја превода коју сам имао у то време је била прилагођена ситуацији у којој је превод софтвера на српски још био релативно свежа ствар. За данашње појмове многе одлуке у вези са тим преводом су застареле, а и ја имам више искуства, па је било природно да детаљно ревидирам и прилагодим превод. Уједно сам додао нове преводе додатака које ELinks није имао 2005., на пример подршке за BitTorrent.
Превод ELinks-а сам дотерао уз помоћ мог програма poe, и уједно сам видео неколико начина на које он може даље да се побољша.