User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

New bash "operator"   |n   pipes into more than 1 pipe

Tue Sep 14, 2021 12:59 pm

In this posting "C script" pipn.c was posted:
viewtopic.php?f=33&t=319473&p=1913242#p1913242

Normally "n" is no executable:

Code: Select all

$ which n
$ 

Now creating "n" link to "~/pipn.c" is all that is needed:

Code: Select all

$ sudo ln -s ~/pipn.c /usr/local/bin/n

Simple demo for piping into 3 pipes, with 2nd "pipe of pipes":

Code: Select all

$ cat /etc/X11/rgb.txt |n 'head -3' "head -55 | tail -17 | wc" "tail -2"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407
144 238 144		light green
144 238 144		LightGreen
$ 

"n" can be used in the sub pipes as well, with "cat|n":

Code: Select all

$ cat /etc/X11/rgb.txt |n 'head -3' "cat|n 'head -55 | tail -17 | wc' 'tail -2'"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407
144 238 144		light green
144 238 144		LightGreen
$ 

Or just "n":

Code: Select all

$ cat /etc/X11/rgb.txt |n 'head -3' "n 'head -55 | tail -17 | wc' 'tail -2'"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407
144 238 144		light green
144 238 144		LightGreen
$ 

In case normal pipe is good enough for your needs, ok.
If you want to be able to pipe into more than one pipe, you now know "|n".
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: New bash "operator"   |n   pipes into more than 1 pipe

Tue Sep 14, 2021 1:38 pm

All pipes and pipe commands run in parallel:
https://gist.github.com/Hermann-SW2/c69 ... pipn-c-L36

Therefore you can be lucky to get separate output:

Code: Select all

pi@raspberrypi400:~ $ cat /etc/X11/rgb.txt |n 'head -5' "head -5"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
248 248 255		GhostWhite
245 245 245		white smoke
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
248 248 255		GhostWhite
245 245 245		white smoke
pi@raspberrypi400:~ $ 

Or get mixed output for same command:

Code: Select all

pi@raspberrypi400:~ $ cat /etc/X11/rgb.txt |n 'head -5' "head -5"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
255 250 250		snow
248 248 255		ghost white
248 248 255		ghost white
248 248 255		GhostWhite
248 248 255		GhostWhite
245 245 245		white smoke
245 245 245		white smoke
pi@raspberrypi400:~ $ 

This can easily be resolved in redirecting output of the pipes into files, if mixed output is unwanted:

Code: Select all

pi@raspberrypi400:~ $ cat /etc/X11/rgb.txt |n 'head -5' "head -5 > out"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
248 248 255		GhostWhite
245 245 245		white smoke
pi@raspberrypi400:~ $ cat out
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
248 248 255		GhostWhite
245 245 245		white smoke
pi@raspberrypi400:~ $ 
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html


User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: New bash "operator"   |n   pipes into more than 1 pipe

Tue Sep 14, 2021 3:16 pm

trejan wrote:
Tue Sep 14, 2021 3:06 pm
Process substitution + tee can do this already. No additional code needed.
You can definitely not do that with tee:

Code: Select all

$ cat /etc/X11/rgb.txt | tee >(head -3) | tail -2
144 238 144		light green
144 238 144		LightGreen
$ 

Different output to:

Code: Select all

$ cat /etc/X11/rgb.txt |n "head -3" "tail -2"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
144 238 144		light green
144 238 144		LightGreen
$ 

Please show how you do what "|n" did in the previous example with process substition, as stated in the other thread I cannot see how process substitutions can help to pipe one input to multiple pipes.
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

trejan
Posts: 3857
Joined: Tue Jul 02, 2019 2:28 pm

Re: New bash "operator"   |n   pipes into more than 1 pipe

Tue Sep 14, 2021 3:21 pm

HermannSW wrote:
Tue Sep 14, 2021 3:16 pm
You can definitely not do that with tee:

Code: Select all

$ cat /etc/X11/rgb.txt | tee >(head -3) | tail -2
144 238 144		light green
144 238 144		LightGreen
$ 
It didn't work because you didn't do it properly.

Code: Select all

$ cat /etc/X11/rgb.txt | tee >(head -3) >(tail -2) > /dev/null
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250             snow
248 248 255             ghost white
144 238 144             light green
144 238 144             LightGreen

User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: New bash "operator"   |n   pipes into more than 1 pipe

Tue Sep 14, 2021 6:51 pm

trejan wrote:
Tue Sep 14, 2021 3:21 pm
It didn't work because you didn't do it properly.

Code: Select all

$ cat /etc/X11/rgb.txt | tee >(head -3) >(tail -2) > /dev/null
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250             snow
248 248 255             ghost white
144 238 144             light green
144 238 144             LightGreen

Than you for correcting me!

I know tee for decades -- but only ever saw the single "[FILE]" in synopsis, and not the "files" plural:

Code: Select all

$ man tee | head -6
TEE(1)                           User Commands                          TEE(1)

NAME
       tee - read from standard input and write to standard output and files

SYNOPSIS
       tee [OPTION]... [FILE]...
$

Depending on execution speed, output can happen after command prompt is already available:

Code: Select all

pi@raspberrypi400:~ $ echo -e "1\n2\n3\n4" | tee >(wc) >(wc)
1
2
3
4
pi@raspberrypi400:~ $       4       4       8
      4       4       8

This can be corrected by appending "| cat":

Code: Select all

pi@raspberrypi400:~ $ echo -e "1\n2\n3\n4" | tee >(wc) >(wc) | cat
1
2
3
4
      4       4       8
      4       4       8
pi@raspberrypi400:~ $ 

So your method of

Code: Select all

... | tee >(cmd1) >(cmd2) ... >(cmdN) > /dev/null
circumvents this, all N command pipes get same input.

Here it can be seen why standard output should go to /dev/null
(because pipe after tee input is different to the N command inputs):

Code: Select all

pi@raspberrypi400:~ $ echo -e "1\n2\n3\n4" | tee >(wc) >(wc) | wc
      6      10      56
pi@raspberrypi400:~ $ 
Last edited by HermannSW on Tue Sep 14, 2021 7:10 pm, edited 1 time in total.
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: New bash "operator"   |n   pipes into more than 1 pipe

Tue Sep 14, 2021 7:06 pm

HermannSW wrote:
Tue Sep 14, 2021 6:51 pm

So your method of

Code: Select all

... | tee >(cmd1) >(cmd2) ... >(cmdN) > /dev/null
circumvents this, all N command pipes get same input.

Sometimes the command prompt comes too early:

Code: Select all

$ cat /etc/X11/rgb.txt | tee >(head -3) >(head -55 | tail -17 | wc) >(tail -2) > /dev/null
144 238 144		light green
$ 144 238 144		LightGreen
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407

"| cat" has to be used properly (with tee in subshell) in order to delay command prompt, but still get correct output:

Code: Select all

$ cat /etc/X11/rgb.txt | (tee >(head -3) >(head -55 | tail -17 | wc) >(tail -2) > /dev/null) | cat
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
144 238 144		light green
144 238 144		LightGreen
     17      79     407
$ 

So the correct way of doing multiple piping should be:

Code: Select all

... | (tee >(cmd1) >(cmd2) ... >(cmdN) > /dev/null) ...

P.S:
We talked about this before, since all pipes are processed in parallel, same command output can be different to the one shown above:

Code: Select all

$ cat /etc/X11/rgb.txt | (tee >(head -3) >(head -55 | tail -17 | wc) >(tail -2) > /dev/null) | cat
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407
144 238 144		light green
144 238 144		LightGreen
$
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

User avatar
dickon
Posts: 2112
Joined: Sun Dec 09, 2012 3:54 pm
Location: Home, in Towcester

Re: New bash "operator"   |n   pipes into more than 1 pipe

Wed Sep 15, 2021 8:21 am

That is surprisingly horrible. Congratulations.

My main objections are:
  • It's unsafe
  • It won't work if /tmp is mounted noexec (which isn't all that uncommon)
  • It won't work if /tmp/pipn.c exists but isn't executable
  • It won't work if /tmp/pipn.c exists, is older than your own ~/pipn.c, but isn't owned by you
  • It won't work for anyone else if your ~/pipn.c isn't readable by them (for whatever reason)
  • I fail to see what it buys you over simply sticking a precompiled copy in /usr/local/bin/
Perhaps I'm missing something.
As it is apparently board policy to disallow any criticism of anything, as it appears to criticise something is to criticise all the users of that something, I will no longer be commenting in threads which are not directly relevant to my uses of the Pi.

User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: New bash "operator"   |n   pipes into more than 1 pipe

Wed Sep 15, 2021 6:52 pm

I see your points, and if you don't like C scripts, you don't need to use them.
Motivation can be found in intial posting of C forum thread:
viewtopic.php?f=33&t=319473#p1912584

Basically, all in a single file, bash script, C code, can be easily moved somewhere, just modify and immediatly use modified version without doing anything. The new bash operator script easily can just be a compiled C program (although it is not needed since Linux tee command does a better job). C scripts allow to split stuff between bash code and C code, no need to do that, but for development and use of my "gamepad" it was the right solution for me (low level gamepad event code in C from jason White, high level code in bash):
https://github.com/Hermann-SW/4DoF_robo ... ls/gamepad
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

User avatar
dickon
Posts: 2112
Joined: Sun Dec 09, 2012 3:54 pm
Location: Home, in Towcester

Re: New bash "operator"   |n   pipes into more than 1 pipe

Wed Sep 15, 2021 8:23 pm

Mmm, but traditionally you'd use something like a shar file for that sort of thing, and you'd be in a much better state for it. As described in that post, your 'C scripts' are downright dangerous: anyone who manages to get any form of shell on your machine stands a good chance of getting a shell as your user, which may well end up as a root shell given the NOPASSWD sudo issue debated elsewhere...

Not a fan, I'm afraid. Not a fan at all.
As it is apparently board policy to disallow any criticism of anything, as it appears to criticise something is to criticise all the users of that something, I will no longer be commenting in threads which are not directly relevant to my uses of the Pi.

ejolson
Posts: 8613
Joined: Tue Mar 18, 2014 11:47 am

Re: New bash "operator"   |n   pipes into more than 1 pipe

Wed Sep 15, 2021 9:31 pm

HermannSW wrote:
Tue Sep 14, 2021 12:59 pm
In this posting "C script" pipn.c was posted:
viewtopic.php?f=33&t=319473&p=1913242#p1913242

Normally "n" is no executable:

Code: Select all

$ which n
$ 

Now creating "n" link to "~/pipn.c" is all that is needed:

Code: Select all

$ sudo ln -s ~/pipn.c /usr/local/bin/n

Simple demo for piping into 3 pipes, with 2nd "pipe of pipes":

Code: Select all

$ cat /etc/X11/rgb.txt |n 'head -3' "head -55 | tail -17 | wc" "tail -2"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407
144 238 144		light green
144 238 144		LightGreen
$ 

"n" can be used in the sub pipes as well, with "cat|n":

Code: Select all

$ cat /etc/X11/rgb.txt |n 'head -3' "cat|n 'head -55 | tail -17 | wc' 'tail -2'"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407
144 238 144		light green
144 238 144		LightGreen
$ 

Or just "n":

Code: Select all

$ cat /etc/X11/rgb.txt |n 'head -3' "n 'head -55 | tail -17 | wc' 'tail -2'"
! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
255 250 250		snow
248 248 255		ghost white
     17      79     407
144 238 144		light green
144 238 144		LightGreen
$ 

In case normal pipe is good enough for your needs, ok.
If you want to be able to pipe into more than one pipe, you now know "|n".
Don't people usually use tee for this?

https://man7.org/linux/man-pages/man1/tee.1.html

User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: New bash "operator"   |n   pipes into more than 1 pipe

Wed Sep 15, 2021 10:24 pm

Yes, see above in this thread, @trejan showed how to use tee correctly to do exactly that.
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

User avatar
dickon
Posts: 2112
Joined: Sun Dec 09, 2012 3:54 pm
Location: Home, in Towcester

Re: New bash "operator"   |n   pipes into more than 1 pipe

Thu Sep 16, 2021 10:57 am

ejolson wrote:
Wed Sep 15, 2021 9:31 pm
Don't people usually use tee for this?
Yeah. I'm more criticising the approach as implemented, which is extremely dangerous on multiuser machines with potentially hostile users on them. All you'd need to do to exploit it is stick an @reboot entry in a user's crontab to create a script to create a suid-user shell somewhere before doing whatever the untrojaned 'script' was designed to do (one per likely command, so /tmp/pipn.c in this case; others have been mentioned), wait for a reboot, wait for the victim to run it, and you're done, hopefully with your victim none the wiser. It isn't sensible, and it isn't safe, and I can't say I'm entirely happy at it being advocated for on a forum like this where naive newbies might come across it and think it's a good idea.

There are ways to mitigate the problems -- the obvious one would be to put the resultant binaries somewhere not under the control of an attacker, such as a ~/.cscache directory or similar -- but that isn't what's happening here.

Yeah. Horrible.
As it is apparently board policy to disallow any criticism of anything, as it appears to criticise something is to criticise all the users of that something, I will no longer be commenting in threads which are not directly relevant to my uses of the Pi.

GlowInTheDark
Posts: 2098
Joined: Sat Nov 09, 2019 12:14 pm

Re: New bash "operator"   |n   pipes into more than 1 pipe

Thu Sep 16, 2021 11:13 am

Yes, but it is all much-ado-about-nothing because we're not TALKING about a "multiuser machines with potentially hostile users on them". We are talking about a Raspberry Pi, which is almost certainly single user and is generally treated as basically in the same security model as a typical home Windows PC - i.e., no security.

And, not only that, but the posts I've seen so far violate a certain sig notation, that says that posters shouldn't criticize other poster's work product. Note: I AM NOT MAKING ANY STATEMENT about whether it is good or not; I am just comparing things I've read on this (and other) threads.
Poster of inconvenient truths.

Back from a short, unplanned vacation. Did you miss me?

User avatar
dickon
Posts: 2112
Joined: Sun Dec 09, 2012 3:54 pm
Location: Home, in Towcester

Re: New bash "operator"   |n   pipes into more than 1 pipe

Thu Sep 16, 2021 11:26 am

We're talking about scripts which can be run under Unix -- Pis, yes, but these things are hardly exclusive to that platform. And who are you to tell me that I have to trust every user on every Pi I own with every byte of data on said Pis?

For your use-case, you're probably right. For *everybody*'s? No. And what's stopping (eg.) a student coming across this, thinking it's a good idea, and copying it up to a university network? Nothing that I can see.
As it is apparently board policy to disallow any criticism of anything, as it appears to criticise something is to criticise all the users of that something, I will no longer be commenting in threads which are not directly relevant to my uses of the Pi.

bjtheone
Posts: 1581
Joined: Mon May 20, 2019 11:28 pm
Location: The Frozen North (AKA Canada)

Re: New bash "operator"   |n   pipes into more than 1 pipe

Fri Sep 17, 2021 7:03 pm

GlowInTheDark wrote:
Thu Sep 16, 2021 11:13 am
Yes, but it is all much-ado-about-nothing because we're not TALKING about a "multiuser machines with potentially hostile users on them". We are talking about a Raspberry Pi, which is almost certainly single user and is generally treated as basically in the same security model as a typical home Windows PC - i.e., no security.
Learning and practicing "good security" is never a bad idea. Teaching "good security" is always a good idea.

Plus many of my Pi's at home are true multi user machines and sudo is controlled. You obviously have never met an inquisitive 12 year old with internet access....

GlowInTheDark
Posts: 2098
Joined: Sat Nov 09, 2019 12:14 pm

Re: New bash "operator"   |n   pipes into more than 1 pipe

Fri Sep 17, 2021 8:23 pm

Luckily, I was smart enough to avoid that trap.
Poster of inconvenient truths.

Back from a short, unplanned vacation. Did you miss me?

User avatar
HermannSW
Posts: 4821
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: New bash "operator"   |n   pipes into more than 1 pipe

Sun Sep 19, 2021 7:53 am

dickon wrote:
Wed Sep 15, 2021 8:21 am
My main objections are:
  • It's unsafe
  • It won't work if /tmp is mounted noexec (which isn't all that uncommon)
  • It won't work if /tmp/pipn.c exists but isn't executable
  • It won't work if /tmp/pipn.c exists, is older than your own ~/pipn.c, but isn't owned by you
  • It won't work for anyone else if your ~/pipn.c isn't readable by them (for whatever reason)
  • I fail to see what it buys you over simply sticking a precompiled copy in /usr/local/bin/
On the very last bullet, "mixed bash and C" execution, or "C scripts".
dickon wrote:
Thu Sep 16, 2021 10:57 am
Yeah. I'm more criticising the approach as implemented, which is extremely dangerous on multiuser machines with potentially hostile users on them. All you'd need to do to exploit it is stick an @reboot entry in a user's crontab to create a script to create a suid-user shell somewhere before doing whatever the untrojaned 'script' was designed to do (one per likely command, so /tmp/pipn.c in this case; others have been mentioned), wait for a reboot, wait for the victim to run it, and you're done, hopefully with your victim none the wiser. It isn't sensible, and it isn't safe, and I can't say I'm entirely happy at it being advocated for on a forum like this where naive newbies might come across it and think it's a good idea.

There are ways to mitigate the problems -- the obvious one would be to put the resultant binaries somewhere not under the control of an attacker, such as a ~/.cscache directory or similar -- but that isn't what's happening here.
First, regarding the subject of this thread, I already agreed with @trejan that "tee" is better than using "|n".

Next, I think I have addressed all that. I completely got rid of need to create any auxiliary filesystem file. The C code extracted from C script and compiled with gcc ends up in an anonymous file that lives in RAM (with memfd_create() system call), with no links from filesystem. ELF binary gets created every time (in RAM) when script is executed, then ELF gets run from memory, and finally disappears immediately after it was executed (directly when binary execution starts, by MFD_CLOEXEC flag). This was possible by new C memrun tool, see github repo and documentation for details:
https://github.com/Hermann-SW/memrun/tr ... r/C#memrun

With memrun "C++ scripts" that "run from memory" became possible:

Code: Select all

pi@raspberrypi400:~/memrun/C $ echo "2^64" | bc -q | ./run_from_memory_cin.cpp 
foo
bar 42
18446744073709551616
pi@raspberrypi400:~/memrun/C $ 
This is (executable) run_from_memory_cin.cpp producing above mixed bash and C++ output:
run_from_memory_cin.cpp.html.png
run_from_memory_cin.cpp.html.png
run_from_memory_cin.cpp.html.png (20.23 KiB) Viewed 703 times
https://github.com/Hermann-SW/memrun
https://stamm-wilbrandt.de/2wheel_balancing_robot
https://stamm-wilbrandt.de/en#raspcatbot
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

Return to “Raspberry Pi OS”