LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-24-2022, 05:32 PM   #16
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206

Returrning my thoughts to the original question...

Quote:
Originally Posted by peonerovv View Post
I want to write a simple terminal program (I'm on linux, if that's important), that will be able to take a piped input. What I mean is the same thing grep does.
...

I want to be able to fetch an input into my program with the pipe (|) symbol and then give arguments that will manipulate what the program does to the input. C will work just fine for it.
In C it is simply a matter of reading input from the *FILE stream named stdin. When stdio.h is included, stdin is always available when a C program starts so you don't have to do anything special to read from it. From man stdin:

Code:
NAME
       stdin, stdout, stderr - standard I/O streams

SYNOPSIS
       #include <stdio.h>

       extern FILE *stdin;
       extern FILE *stdout;
       extern FILE *stderr;

DESCRIPTION
       Under  normal  circumstances every UNIX program has three streams opened for it when it starts up,
       one for input, one for output, and one for printing diagnostic or error messages.  These are typi‐
       cally  attached  to the user's terminal (see tty(4)) but might instead refer to files or other de‐
       vices, depending on what the parent process chose to set up.  (See also the "Redirection"  section
       of sh(1).)
Here is a simple example which will prepend line numbers to anything sent via stdin:

Code:
#include <stdio.h>
#include <stdlib.h>

int main(){
        int lcount = 0;
        char *line = NULL;
        size_t len = 0;
        while (getline(&line, &len, stdin) >= 0)
                {
                                printf("%d: %s", ++lcount, line);
                                free(line);
                                line = NULL;
                }
        return 0;
}
You can easily adapt that to perform whatever action you desire with the input stream.

You can do this more easily using a shell script as well. Once again, stdin is always availlable and is the default input for most purposes so that you do not even need to reference it explicitly:

Code:
#!/bin/bash

while read aline; do
        echo "$((++lcount)): ${aline}"
done
Hope that helps!

Last edited by astrogeek; 03-24-2022 at 07:50 PM. Reason: Simplified C example, again
 
Old 03-24-2022, 06:06 PM   #17
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,918

Rep: Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035
Quote:
Originally Posted by danielbmartin View Post
I'm confessing ignorance here...

What is "not safe?" What harm does it do? Does it make my code run slower? Does it make my computer vulnerable to malware?

Daniel B. Martin

.
If you look again at the example I posted, you'll see I asked it to run one script, but it actually ran a completely different one. So, yes, potentially it's vulnerable to abuse, but the short answer is that it's just wrong.
 
Old 03-25-2022, 07:01 AM   #18
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,918

Rep: Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035Reputation: 5035
You can move the free() and line=NULL outside the loop. getline() will reuse the buffer, calling realloc() only if it is not currently large enough to hold a subsequent line.
 
1 members found this post helpful.
Old 03-28-2022, 08:52 AM   #19
hunkemoller
LQ Newbie
 
Registered: Oct 2013
Distribution: ubuntu
Posts: 7

Rep: Reputation: Disabled
get the habit of using (may need to download) shellcheck to vet scripts

Code:
% cat bad.sh       
#
#/bin/bash
echo "hello $(date)"
% shellcheck bad.sh

In bad.sh line 1:
#
^-- SC2148 (error): Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
For more information:
  https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y...
 
Old 03-28-2022, 09:07 AM   #20
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
Taking advice from astrogeek and constructive criticism from GazL, I offer this example in response to the OP's question.

Advice, corrections, improvements are welcome.

This script ...
Code:
#!/bin/bash
#   Daniel B. Martin   Mar22

#  To execute this program, launch a terminal session and enter:
#  bash /home/daniel/Desktop/LQfiles/dbm2324.bin

# This program inspired by ...
# https://www.linuxquestions.org/questions/programming-9/
#   how-to-write-a-terminal-program-that-i-can-pipe-the-input-into-it-4175709904/

# This program solicits user input,
#   sorts the words in each line alphabetically,
#   displays each sorted line,
#   and builds a file of all sorted lines.

# File identification
     Path=${0%%.*}
  OutFile=$Path"out.txt"

echo
echo 'This program solicits keyboard entry of text lines.'
echo 'The words in each line are reordered by an alphabetic sort.'
echo 'An output file is created which contains all the sorted lines.'
echo

rm -f $OutFile   # Blow away a leftover file.
while :  # This sets up an infinite loop.
do
  echo; echo 'Please enter a line of text.  A null line ends execution.'
  read aline
  if [ -z "$aline" ]; then break; fi   # If null string, exit loop.
  sline=$(tr ' ' '\n' <<< "$aline"  \
         |sort                      \
         |tr '\n' ' ')
  echo 'Before sorting: '$aline
  echo 'After sorting:  '$sline
  echo $sline >>$OutFile  # Append one sorted line to OutFile.
done

echo; echo 'This is the OutFile...'; cat $OutFile
echo; echo 'Normal end of job.'; exit
It produced this on-screen result...
Code:
This program solicits keyboard entry of text lines.
The words in each line are reordered by an alphabetic sort.
An output file is created which contains all the sorted lines.


Please enter a line of text.  A null line ends execution.
mary had a little lamb
Before sorting: mary had a little lamb
After sorting:  a had lamb little mary

Please enter a line of text.  A null line ends execution.
its fleece was white as snow
Before sorting: its fleece was white as snow
After sorting:  as fleece its snow was white

Please enter a line of text.  A null line ends execution.


This is the OutFile...
a had lamb little mary
as fleece its snow was white

Normal end of job.
Daniel B. Martin

.
 
1 members found this post helpful.
Old 03-28-2022, 11:06 AM   #21
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,784

Rep: Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937
danielbmartin,
A bit off topic but I will try to give a quick answer about the shebang line.

bash myscript

In your example your using bash to run the script and since the shebang line starts with a # it is treated as a comment.

However if you run the script as a stand alone executable program, the shebang line is passed to the interpreter basically like a command. Anything after the command i.e /bin/bash is treated like an option.

#!/usr/bin/env python3

In the above shebang example runs env which searches and runs the python3

Actually shebang i.e #! is a magic number.

It could lead to some catastrophic event if your comment is interpreted as real command like rm...
 
1 members found this post helpful.
Old 03-28-2022, 12:54 PM   #22
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,880
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
Concrete example for the 'rm-shebang': a program that deletes itself
Code:
echo '#!/bin/rm' >remove.me; chmod +x remove.me; ./remove.me
a variation
Code:
echo '#!/bin/rm' >remove.me; chmod +x,-w remove.me; ./remove.me
rm: Remove ./remove.me? y
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Awk: Input from one line, execute program; input from next line, execute program C.L. Programming 9 09-27-2010 12:06 AM
LXer: Determine If Shell Input is Coming From the Terminal or From a Pipe LXer Syndicated Linux News 0 02-11-2010 06:30 AM
Can't get user input when using a pipe to my C++ program ta0kira Programming 18 04-22-2006 12:53 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:00 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration