2017-11-24 29 views
5

के लिए असाइन किए गए टर्मिनल डिवाइस का पता लगाने के लिए मैं पेजर pspg लिख रहा हूं। वहां मुझे निम्नलिखित मुद्दे को हल करना है। stdin से पढ़ने के बाद मुझे टर्मिनल से पढ़ने के लिए पाइप से पिछले पढ़ने से stdin पुन: असाइन करना चाहिए। ऐसा कोई:इंटरैक्टिव काम

मैं

freopen("/dev/tty", "r", stdin) 

इस्तेमाल किया लेकिन यह काम नहीं करता है, जब पेजर आदेश से इस्तेमाल किया गया था कि क्या इस मामले में सीधे

su - someuser -c 'export PAGER=pspg psql somedb' 

निष्पादित नहीं किया गया था, मैं एक त्रुटि मिली डिवाइस या पता

मैं एक समाधान पाया - अब, कोड की तरह दिखता है:

if (freopen("/dev/tty", "r", stdin) == NULL) 
{ 
    /* 
    * try to reopen pty. 
    * Workaround from: 
    * https://cboard.cprogramming.com/c-programming/172533-how-read-pipe-while-keeping-interactive-keyboard-c.html 
    */ 
    if (freopen(ttyname(fileno(stdout)), "r", stdin) == NULL) 
    { 
     fprintf(stderr, "cannot to reopen stdin: %s\n", strerror(errno)); 
     exit(1); 
    } 
} 

इस मामले में सौंपा टर्मिनल डिवाइस का पता लगाने के एक सही तरीका क्या है?

लेकिन यह कामकाज सही नहीं है। यह एक मुद्दा तय किया, लेकिन अगला आ रहा है। जब कोई उपयोगकर्ता वर्तमान उपयोगकर्ता से अलग होता है, तो फिर से खोलें त्रुटि अनुमति के साथ विफल रहता है अनुमति से मना कर दी गई है। तो इस कामकाज का उपयोग मेरे उद्देश्यों के लिए नहीं किया जा सकता है।

+0

मैं आपकी समस्या को समझ नहीं पा रहा हूं 'su-user -c' cat'' मेरे टर्मिनल इनपुट और मेरे टर्मिनल में आउटपुट पढ़ता है। "टर्मिनल से पढ़ने के लिए पाइप से पिछली पढ़ाई।", जो मुझे समझ में नहीं आता है। मैं आपको बता रहा हूं कि क्योंकि मुझे XY समस्या पर संदेह है, आप जो करने की कोशिश कर रहे हैं वह बहुत अजीब है। – Stargateur

+0

पेजर stdin से डेटा पढ़ता है, लेकिन इंटरैक्टिव होने के लिए/dev/tty पर स्विच करने की आवश्यकता है। स्विच एक समस्या है। सामान्य अनुप्रयोग यह नहीं करता है, और पेरेंट पर्यावरण द्वारा तैयार stdin, stdout का उपयोग कर। पेजर अलग है - stdin से डेटा पढ़ता है, लेकिन कीबोर्ड को भी पढ़ने की जरूरत है। –

उत्तर

2

क्या less इस स्थिति में एफडी 2 (stderr) पर वापस आ गया है। यदि stderr को tty से दूर रीडायरेक्ट किया गया है, तो यह कीबोर्ड इनपुट प्राप्त करने का प्रयास करता है, और केवल पेजिंग के बिना पूरी इनपुट स्ट्रीम प्रिंट करता है।

su का डिज़ाइन कुछ भी बेहतर करने की अनुमति नहीं देता है। नया उपयोगकर्ता मूल उपयोगकर्ता के स्वामित्व वाले टीटी पर एक कमांड चला रहा है, और अप्रिय तथ्य पूरी तरह छुपाया नहीं जा सकता है।

यहाँ है कि इस समस्या नहीं है su के लिए एक अच्छी विकल्प है:

ssh -t localhost -l username sh -c 'command' 

यह निश्चित रूप से, एक छोटे से अधिक भूमि के ऊपर है।

+0

कम stdout से सीधे पढ़ने के लिए है, stdin फिर से खोलने के बिना, मैं क्या कर रहा हूँ और क्या काम नहीं करता है।शायद एक ही संभव तरीका एक ही सेटअप है। –

+0

यह मेरे समाधान के पास सबसे अधिक है –

1

अंत मैं पैटर्न है कि मैं less पेजर में पाया इस्तेमाल किया पर, लेकिन ncurses साथ प्रयोग करने के लिए संशोधित किया गया:

सबसे पहले मैं कुछ tty संबंधित उपकरण के लिए stdin फिर से खोलना करने की कोशिश:

if (!isatty(fileno(stdin))) 
{ 
    if (freopen("/dev/tty", "r", stdin) != NULL) 
     noatty = false; 
    /* when tty is not accessible, try to get tty from stdout */ 
    else if (freopen(ttyname(fileno(stdout)), "r", stdin) != NULL) 
     noatty = false; 
    else 
    { 
     /* 
     * just ensure stderr is joined to tty, usually when reopen 
     * of fileno(stdout) fails - probably due permissions. 
     */ 
     if (!isatty(fileno(stderr))) 
     { 
      fprintf(stderr, "missing a access to terminal device\n"); 
      exit(1); 
     } 
     noatty = true; 
     fclose(stdin); 
    } 
}     
else 
    noatty = false; 

जब मेरे पास tty नहीं है और stdin का उपयोग नहीं कर सकता है, तो मैं newterm फ़ंक्शंस का उपयोग कर रहा हूं, जो इनपुट स्ट्रीम निर्दिष्ट करने की अनुमति देता है:

if (noatty) 
    /* use stderr like stdin. This is fallback solution used by less */ 
    newterm(termname(), stdout, stderr); 
else 
    /* stdin is joined with tty, then use usual initialization */ 
    initscr(); 
संबंधित मुद्दे