Kütüphane komutları kabuktan nasıl çalıştırılır?


27

Bir dizgenin uzunluğunu hesaplamak istedim (bu karma değerdir). Böylece terminali açtım ve şunu yaptım:

$ apropos length

Bu da beni , sonunda bulunan (3)veya (3ssl)ekleyen bir sürü komutla / fonksiyonla geri döndürdü . Şimdi erkek adam bize bunların ne section numbersanlama geldiği hakkında bilgi veriyor .

3   Library calls (functions within program libraries)

Merak ettim, sadece tüm bu emirleri denedim (umarım en azından biri işe yarar)

strcspn (3)          - get length of a prefix substring
strlen (3)           - calculate the length of a string
strnlen (3)          - determine the length of a fixed-size string
strspn (3)           - get length of a prefix substring
wcslen (3)           - determine the length of a wide-character string
wcsnlen (3)          - determine the length of a fixed-size wide-character string

ve her komut için aynı hatadan başka bir şey alamadım

$ strnlen HelloWorld 
$ strnlen: command not found

Evet, biliyorum kabuğunda dize uzunluğunu bulmak için nasıl kullanıyor wc -m, expr lengthve diğer çözümler.

Fakat burada 2 sorum var:

  1. Herhangi birlibrary calls (3) kabuk içinde nasıl kullanılır ?
  2. Diğer komutları değil, yalnızca kitaplık çağrılarını kullanarak dize uzunluğu nasıl hesaplanır?

NOT: Soru genel olarak library callsve kabuktaki kullanımlarına odaklanır . Bu, ilk soruyu cevaplaması daha önemli hale getirir.



4
Temel olarak, Michael'ın cevabı büyük bir hack olsa da, basit cevabı şudur: siz yapmazsınız. Kütüphane aramaları kabukla ilgili değildir . C dilinde programlar yazmak için kullanılırlar. - Daha genel olarak, bir programı kodlamadığınız sürece, manpages okurken sadece 2, 3 ve 9. bölümleri yok sayın.
Spektrum

Konu Dışı, ancak OpenVMS, çok sayıda sistem kütüphanesi işlevine kabuk arabirimi olan "sözcüksel" işlevlere sahiptir.
RonJohn

Yanıtlar:


39

Muhtemelen bunu yapmamalısın , ama yapabilirsin. Kusalananda'nın cevabı eldeki görev için daha iyidir ve konuyu açıklar. Terminalde herhangi bir kütüphane çağrısını nasıl kullanacağınızı özellikle sorduğunuzdan , işte size birkaç yol ...


Minik C derleyicisi ( tcc) Bir destekler -runbayrak Bunu, (yürürlükte) sizi sağlayan küçük bir program yazarak C kodu yorumlamak olabilir yani tek bir çağırma yoluyla terminali içindeki herhangi kütüphane çağrıları kullanın.

strnlenİşlevi şu şekilde çalıştırabilirsiniz :

$ tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", strnlen(argv[1], 1024));}') "Hello world"
11

Bu , Bash'in, zsh'nin ve diğer mermilerin işlem ikamesinitcc , bütün echos'nin sonuçlarını içerdiği okunacak bir dosya vermek için kullanır ; başka seçenekler var.

Bunu sizin için oluşturmak için bir işlev yapabilirsiniz:

call_library_function_s_i() {
    func=$1
    shift
    tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", '$func'(argv[1]));}') "$*"
}
$ call_library_function_s_i strlen hello world

(Ben strlenburada tek bir işlev işlevi olan dizgiyi kullandım -> int - her bir aritelik ve dönüş tipi için ayrı bir işleve ihtiyacınız olacaktı).


Başka bir seçenek ise ,ctypes.sh sararmış olan Tavis Ormandy'nin Bash eklentisidlopen ve dlsym. Bu muhtemelen denediğin şeye en yakın yaklaşım. Örneğin kullanabilirsiniz:

$ dlcall -r uint64 strlen "hello world"

ve beklendiği gibi işlevi çağıracak.

Bu, onu "terminalden" yapmanın en doğrudan yoludur, ancak dağıtım paketlerinizin olması muhtemel değildir, bu nedenle el ile yüklemeniz gerekir (ki bu önemsiz). İşte insanların bunu nasıl yaptıkları hakkında genel bir fikir vermek için kendi web sitesinden bazı bilgilendirici alıntılarctypes.sh :

  • "Bu iğrenç"
  • "Bu durmalı"
  • "Bununla çok ileri gittin"

Diğer mermiler için benzer araçlar olabilir, ama ben onları bilmiyorum. Teoride, basit vakalar için tam olarak bunu yapan bağımsız bir komutun olmamasının bir nedeni yoktur, ancak bir tanesini bulamadığım için biraz şaşırdım ...


... ben de bir tane yaptım! dlcallkütüphane işlevlerini komut satırından çağırmanıza izin verir :

$ dlcall strnlen "hello world" 6
$ dlcall sin 2.5
$ dlcall strchr "hello world" -c ' '

Sınırlı sayıda fonksiyon prototipini destekliyor, şu anda korkunç derecede güvenilir veya esnek değil, ancak şimdi var.


Örneğin Python'upython -c 'import ctypes; import sys; print(ctypes.cdll.LoadLibrary("libc.so.6").strlen(" ".join(sys.argv[1:])))' hello world da kullanabilirsiniz, ancak bu kesinlikle en kolay yol değil. Perl, Ruby ve diğer dillerin kullanabileceğiniz benzer özellikleri var.


Yani sorularınızın cevapları:

  1. Yukarıdaki yaklaşımlardan birini kullanın.
  2. Sen do kütüphaneye sizi bootstrap başka bir emir kullanmak gerekir, ya da yazılım parçasıdır kabuğundan içine kanca söyledi.

Sonuçta, kesinlikle başka bir şekilde bunu yapmaktan daha iyi olacaksın.


2
"dlcall" bana (tamamen aynı değil) Windows "rundll" u hatırlatıyor: support.microsoft.com/en-gb/help/164787/…
pjc50

1
@ pjc50: Kamu hizmeti duyurusu: rundll32 keyfi işlevleri çağırmak için genel bir amaç aracı değildir . Sadece belirli bir imzayla işlevleri çağırmak için kullanılabilir. Ayrıca, bu korkunç bir gelecek kanıtı değil .
Kevin,

29

aproposKomut birçok yönden yararlıdır, ama çok da seni "önemsiz" bir sürü vermek yok. Listede bulunduğunuz şeylerin çoğu, doğrudan kabuktan kullanamadığınız C kitaplığı yordamlarıdır (bu, kılavuzun 3. bölümünün içindir).

Bunları kullanmak için, onları çağıran bir C programı yazmanız gerekir. Bu, bu belirli sitenin kapsadığı konuların kapsamı dışında kalmaktadır (StackOverflow'ta konu üzerinde olacaktır ).

Bunlar, sorularınızın cevaplarıdır:

  1. Yapamazsın, onlar C kütüphanesi yordamları.
  2. Bir C programı yazmadıkça yapamazsın.

Bunu bildiğini biliyorum, ama tamamlık uğruna: Kabuğunda, bir değişkende bir dizge stringvarsa, yapabilirsin.

string='hello world'
printf 'Length of string "%s" is %d\n' "$string" "${#string}"

Bu Length of string "hello world" is 11, 11gelen ${#string}dizgenin uzunluğuna genişleyen terminale basacaktır $string.

Dahili olarak, kabuk, uzunluk hesaplamasını yapmak için listelediğiniz kütüphane aramalarından birini kullanıyor olabilir.

Bu, kabuktaki bir kabuk değişkeninde saklanan bir dize uzunluğunu elde etmenin en etkili yoludur.

Bunun bir POSIX kabuk parametresi genişletmesi olduğunu ${#string}da unutmayın , bu nedenle herhangi bir POSIX uyumluluğu derecesi talep eden tüm kabuklar arasında taşınabilir.


Kütüphane fonksiyonları hakkındaki bölümler iyi bir açıklama, ancak bu cevabın geri kalanı biraz yanıltıcı. OP diyor "Ben sadece bir dize uzunluğunu hesaplamak istedik" kullanmaya gerek yoktur printfburada. Cümlenin bir parçası olarak yazdırmak istiyorsanız, o zaman bu en iyi yol olabilir. Ancak, "bir dize uzunluğunu nasıl alabilirim?" Sorusunun cevabı. ${#string}printf değil , parçadır. Sadece echo ${#string}sadece uzunluğu vermek string_length=${#string}ya da istediğiniz ya da istediğiniz başka bir değişkene atamak istiyorsanız kullanabilirsiniz. printf gerçekten alakalı değil
Adam

1
@Adam Cevapta küçük değişiklikler yaptım. Ben dize uzunluğunu almak oldukça açık olduğunu düşünüyorum ve kullanıcı zaten nasıl yapılacağını bildiklerini söyledi. By kullanarak ile dize uzunluğunu printfBen sadece "kullanımını söyleyerek dışında bir şey eklemek ${#string}(aşikar örnekten ise)".
Kusalananda

15

Bunu sadece bunun için yapmam strlen(), ama bazen C kodunu denemek için yararlı bir hiledir.

user @ host: ~ $ gdb gdb
(gdb) başlangıç
Geçici kesme noktası 1, ... ana ()
(gdb) baskı gergin ("foobar")
1 ABD Doları = 6

İşte gdbGNU hata ayıklayıcısı ve normalde ondan sonra hata ayıklamak için bir program adı alacaktı. Çünkü bizde hiçbir şey yok, bu örnek hata ayıklamayı kendisi veriyor. Sonra startprogramı başlatır ve bundan sonra gdbisteğe bağlı C kodunu çalıştırmak için kullanılabilir.


2
İyi numara, gdb kullanmak. Ancak gdb, geliştirici araçlarının bir parçasıdır ve kütüphane işlevini kullanmak istiyorsanız, geliştirici araçlarını kullanmayı öğrenmeye daha iyi hazır olursunuz.
Dudi Boy

4

Paylaşılan kütüphanelerdeki işlevleri etkileşimli olarak çağırmak için kullanılabilecek bir araç: "Witchcraft Compiler Collection". https://github.com/endrazine/wcc

GitHub sayfasından:

wsh: Cadılık kabuğu

Büyücülük kabuğu, ELF paylaşımlı kütüphanelerini, ELF ET_DYN çalıştırılabilir dosyalarını ve Punk-C'de yazılmış Witchcraft Shell Scriptlerini bir girdi olarak kabul eder. Tüm çalıştırılabilir dosyaları kendi adres alanına yükler ve API'larını gömülü tercümanında programlama için kullanılabilir hale getirir. Bu, Java gibi dillere yansıma yoluyla sağlananlara benzer ikili fonksiyonlar sağlar.

Wsh'nin örnek kullanımı Aşağıdaki komut , wsh/usr/sbin/apache2 içindeki yürütülebilir dosyayı yükler, ap_get_server_banner()başlığını almak için apache içindeki işlevi çağırır ve wshyorumlayıcıda görüntüler.

jonathan@blackbox:~$ wsh /usr/sbin/apache2
> a = ap_get_server_banner()
> print(a)
Apache/2.4.7
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.