Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » GNU/Linux » getpass-Ersatz

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
07.07.2004, 13:47 Uhr
0xdeadbeef
Gott
(Operator)


Moin,

Die Funktion getpass ist ja schon seit längerem deprecated, also hab ich mich mal hingesetzt und eine Art Ersatz dafür geschrieben. Was haltet ihr davon?

C++:
#include <stdio.h>
#include <termio.h>
#include <unistd.h>

char *getnpass(char *buf, size_t buflen, char *prompt) {
  struct termios settings, check;
  tcflag_t old_lflag;
  char *ret = NULL;
  size_t i;
  char c;

  if(0 == tcgetattr(STDOUT_FILENO, &settings)) {
    old_lflag = settings.c_lflag;
    settings.c_lflag &= ~ECHO;
    settings.c_lflag |= ECHONL | ICANON;

    if(0 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &settings)) {
      if(0 == tcgetattr(STDIN_FILENO, &check) &&
     settings.c_lflag == check.c_lflag) {
    printf("%s", prompt);
    /* I'd love to use fgets for simpler code, but I'd have
     * to check for a newline at the end, so I'd have to make
     * two passes which is not cool.
     */

    for(i = 0; (c = getchar()) != '\n' && i < buflen - 1; ++i)
      buf[i] = c;
    buf[i] = 0;
    ret = buf;
      }
      /* Let's hope the tcgetattr-check above never fails, but
       * since we all know and follow the way of the Murphy...
       */

      settings.c_lflag = old_lflag;
      tcsetattr(STDIN_FILENO, TCSAFLUSH, &settings);
      /* This may fail as well, but in that case, things have
       * gone so completely haywire that I don't know what to
       * do anymore, so I'll just return NULL.
       */

    }    
  }

  return ret;
}


Das Error-Handling ist fürchterlich, aber da komm ich leider wegen des seltsamen Rückgabewertes von tcsetattr nicht herum.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 07.07.2004 um 13:48 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
07.07.2004, 16:03 Uhr
0xdeadbeef
Gott
(Operator)


Ich hab mir mal die getpass-Implementierug der glibc angekuckt und darauf aufbauend das hier gebastelt:

C++:
/* Copyright (C) 1992,93,94,95,96,97,98,99,2001 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */


#include <stdio.h>
#include <stdio_ext.h>
#include <termios.h>
#include <unistd.h>

/* It is desirable to use this bit on systems that have it.
   The only bit of terminal state we want to twiddle is echoing, which is
   done in software; there is no need to change the state of the terminal
   hardware.  */


#ifndef TCSASOFT
#define TCSASOFT 0
#endif

char *getnpass (char *buf, size_t bufsize, const char *prompt) {
  FILE *in, *out;
  struct termios s, t;
  int tty_changed;
  ssize_t nread, tmplen;
  char *tmp;

  /* Try to write to and read from the terminal if we can.
     If we can't open the terminal, use stderr and stdin.  */


  in = fopen ("/dev/tty", "w+");
  if (in == NULL) {
    in = stdin;
    out = stderr;
  } else {
    /* We do the locking ourselves.  */
    /* I know __-functions usually aren't meant for programmer
     * use, but according to the information I found on the net,
     * this (among other functions in the stdio_ext.h-Header)
     * is meant for portable access to the stdio FILE structure.
     */

    __fsetlocking (in, FSETLOCKING_BYCALLER);
    out = in;
  }

  flockfile (out);

  /* Turn echoing off if it is on now.  */

  if (tcgetattr (fileno (in), &t) == 0) {
    /* Save the old one. */
    s = t;
    /* Tricky, tricky. */
    t.c_lflag &= ~(ECHO|ISIG);
    tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0);
  } else
    tty_changed = 0;

#ifdef __USE_GNU
  fputs_unlocked(prompt, out);
#else
  fputs(prompt, out);
#endif

#ifdef __USE_MISC
  fflush_unlocked(out);
#else
  fflush(out);
#endif

  /* Read the password.  */
  nread = getline (&tmp, &tmplen, in);
  if (tmp != NULL) {
    if (nread < 0)
      tmp[0] = '\0';
    else if (tmp[nread - 1] == '\n') {
      /* Remove the newline.  */
      tmp[nread - 1] = '\0';
      if (tty_changed) {
        /* Write the newline that was not echoed.  */
        putc_unlocked('\n', out);
      }
    }
  }

  /* Restore the original setting.  */
  if (tty_changed)
    (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);

  funlockfile (out);

  if (in != stdin)
    /* We opened the terminal; now close it.  */
    fclose (in);

  strncpy(buf, tmp, bufsize);
  memset(tmp, 0, tmplen);
  free(tmp);

  return buf;
}



Bearbeitung:

Wenn ich was am Code ändere, kommt es hier rein.


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 07.07.2004 um 16:46 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
07.07.2004, 16:08 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich würde explizit /dev/tty als Datei öffnen, weil man sonst eine andere Funktionaltät als die von getpass hat: Dein Code schlägt im Falle der Umleitung des stdin aus einer Datei fehl.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
07.07.2004, 16:08 Uhr
virtual
Sexiest Bit alive
(Operator)


Oh, hat sich erledigt
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
07.07.2004, 16:12 Uhr
0xdeadbeef
Gott
(Operator)


OK, ich hab noch die _unlocked-Funktionen rausgenommen, um es POSIX-konform zu machen. Wie ist das mit __fsetlocking? Nach dem, was ich gesehen habe, soll das angeblich portabel sein, aber das __ macht mir Kopfschmerzen...
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
07.07.2004, 16:23 Uhr
0xdeadbeef
Gott
(Operator)


Hm. Und warum gehe ich nicht eigentlich so hin?

C++:
char *getnpass(char *buf, size_t bufsize, char *prompt) {
  char *p = getpass(prompt);
  strncpy(buf, p, bufsize);
  memset(p, 0, strlen(p));
  free(p);
  return buf;
}


Ich meine - OK, das ist weniger performant, aber bei der Passworteingabe dürfte das nicht wirklich ins Gewicht fallen, oder?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 07.07.2004 um 16:24 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
07.07.2004, 16:36 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


ich dachte getpass ist deprecated?
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
07.07.2004, 16:40 Uhr
0xdeadbeef
Gott
(Operator)


Ja, und zwar mit der Begründung, dass es nen statischen Buffer zurückliefert. Ein ziemlich komischer Mechanismus, das.

Naja, ich werd von jetzt an den zweiten Code benutzen, also das, was vom GNU-Code abgeleitet ist. Das gefällt mir ganz gut.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
08.07.2004, 09:51 Uhr
virtual
Sexiest Bit alive
(Operator)


Ne, da gefällt mir die Variante aus Post 001 besser: Bei der Variante aus Post 005 hast Du zwar das Problem mit dem statischen Buffer umschifft, aber das auch nur teilweise; multithreadingfähig ist das ding noch immer nicht.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
08.07.2004, 17:17 Uhr
0xdeadbeef
Gott
(Operator)


Den meinte ich ja auch. Aber das mit der Multithreading-Fähigkeit ist ein gutes Argument für den Fall, dass mich mal jemand fragt, warum.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 08.07.2004 um 17:17 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ GNU/Linux ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: