~ubuntu-branches/ubuntu/precise/util-linux/precise-proposed

« back to all changes in this revision

Viewing changes to login-utils/agetty.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-06-20 22:31:50 UTC
  • mfrom: (1.6.3 upstream) (4.5.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110620223150-lz8wrv0946ihcz3z
Tags: 2.19.1-2ubuntu1
* Merge from Debian unstable, remaining changes:
  - Build for multiarch.
  - Add pre-depends on multiarch-support.
  - configure.ac: don't try to be clever about extracting a path name from
    $libdir to append to /usr in a way that's not overridable; instead,
    reuse the built-in configurable libexecdir.
  - Fix up the .pc.in files to know about libexecdir, so our substitutions
    don't leave us with unusable pkg-config files.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.
  - Since upstart is required in Ubuntu, the hwclock.sh init script is not
    called on startup and the hwclockfirst.sh init script is removed.
  - Drop depends on initscripts for the above.
  - Replace hwclock udev rule with an Upstart job.
  - For the case where mount is called with a directory to mount, look
    that directory up in mountall's /lib/init/fstab if we couldn't find
    it mentioned anywhere else.  This means "mount /proc", "mount /sys",
    etc. work.
  - mount.8 points to the cifs-utils package, not the obsolete smbfs one. 
* Dropped changes:
  - mount.preinst: lsb_release has been fixed in lucid and above to be
    usable without configuration, so we don't have to diverge from Debian
    here anymore.
* Changes merged upstream:
  - sfdisk support for '+' with '-N'
  - mount/umount.c: fix a segfault on umount with empty mtab entry
  - Fix arbitrary unmount with fuse security issue

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#include <sys/socket.h>
33
33
#include <netdb.h>
34
34
 
35
 
#include "xstrncpy.h"
 
35
#include "strutils.h"
36
36
#include "nls.h"
37
37
#include "pathnames.h"
 
38
#include "c.h"
38
39
 
39
40
#if defined(__FreeBSD_kernel__)
40
41
#include <pty.h>
137
138
#define F_CUSTISSUE     (1<<6)          /* give alternative issue file */
138
139
#define F_NOPROMPT      (1<<7)          /* don't ask for login name! */
139
140
#define F_LCUC          (1<<8)          /* Support for *LCUC stty modes */
 
141
#define F_KEEPSPEED     (1<<9)          /* Follow baud rate from kernel */
 
142
#define F_KEEPCFLAGS    (1<<10)         /* Reuse c_cflags setup from kernel */
140
143
 
141
144
/* Storage for things detected while the login name was read. */
142
145
 
207
210
void parse_speeds P_((struct options *op, char *arg));
208
211
void update_utmp P_((char *line));
209
212
void open_tty P_((char *tty, struct termios *tp, int local));
210
 
void termio_init P_((struct termios *tp, int speed, struct options *op));
 
213
void termio_init P_((struct termios *tp, struct options *op));
211
214
void auto_baud P_((struct termios *tp));
212
215
void do_prompt P_((struct options *op, struct termios *tp));
213
216
void next_speed P_((struct termios *tp, struct options *op));
301
304
    tcsetpgrp(0, getpid());
302
305
    /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
303
306
    debug("calling termio_init\n");
304
 
    termio_init(&termios, options.speeds[FIRST_SPEED], &options);
 
307
    termio_init(&termios, &options);
305
308
 
306
309
    /* write the modem init string and DON'T flush the buffers */
307
310
    if (options.flags & F_INITSTRING) {
308
311
        debug("writing init string\n");
309
 
        write(1, options.initstring, strlen(options.initstring));
 
312
        ignore_result( write(1, options.initstring, strlen(options.initstring)) );
310
313
    }
311
314
 
312
315
    if (!(options.flags & F_LOCAL)) {
356
359
 
357
360
    /* Now the newline character should be properly written. */
358
361
 
359
 
    (void) write(1, "\n", 1);
 
362
    ignore_result( write(1, "\n", 1) );
360
363
 
361
364
    /* Let the login program take care of password validation. */
362
365
 
363
366
    (void) execl(options.login, options.login, "--", logname, NULL);
364
367
    error(_("%s: can't exec %s: %m"), options.tty, options.login);
365
 
    exit(0);  /* quiet GCC */
366
368
}
367
369
 
368
370
/* parse-args - parse command-line arguments */
377
379
    extern int optind;                  /* getopt */
378
380
    int     c;
379
381
 
380
 
    while (isascii(c = getopt(argc, argv, "8I:LH:f:hil:mt:wUn"))) {
 
382
    while (isascii(c = getopt(argc, argv, "8cI:LH:f:hil:mst:wUn"))) {
381
383
        switch (c) {
 
384
        case 'c':
 
385
            op->flags |= F_KEEPCFLAGS;
 
386
            break;
382
387
        case '8':
383
388
            op->eightbits = 1;
384
389
            break;
447
452
        case 'n':
448
453
            op->flags |= F_NOPROMPT;
449
454
            break;
 
455
        case 's':
 
456
            op->flags |= F_KEEPSPEED;           /* keep kernel defined speed */
 
457
            break;
450
458
        case 't':                               /* time out */
451
459
            if ((op->timeout = atoi(optarg)) <= 0)
452
460
                error(_("bad timeout value: %s"), optarg);
597
605
        if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {
598
606
            flock(lf, LOCK_EX);
599
607
            if ((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
600
 
                write(ut_fd, &ut, sizeof(ut));
 
608
                ignore_result( write(ut_fd, &ut, sizeof(ut)) );
601
609
                close(ut_fd);
602
610
            }
603
611
            flock(lf, LOCK_UN);
685
693
     * 0622 is suitable for SYSV <4 because /bin/login does not change
686
694
     * protections. SunOS 4 login will change the protections to 0620 (write
687
695
     * access for group tty) after the login has succeeded.
 
696
     *
 
697
     * Linux login(1) will change tty permissions.
688
698
     */
689
699
 
690
700
    /*
691
701
     * Let us use 0600 for Linux for the period between getty and login
692
702
     */
693
 
 
694
 
    (void) chown(tty, 0, 0);                    /* root, sys */
695
 
    (void) chmod(tty, 0600);                    /* 0622: crw--w--w- */
 
703
    ignore_result( chown(tty, 0, 0) );          /* root, sys */
 
704
    ignore_result( chmod(tty, 0600) );          /* 0622: crw--w--w- */
696
705
    errno = 0;                                  /* ignore above errors */
697
706
}
698
707
 
702
711
char area[1024];
703
712
 
704
713
void
705
 
termio_init(tp, speed, op)
 
714
termio_init(tp, op)
706
715
     struct termios *tp;
707
 
     int     speed;
708
716
     struct options *op;
709
717
{
 
718
    speed_t ispeed, ospeed;
 
719
 
 
720
    if (op->flags & F_KEEPSPEED) {
 
721
        ispeed = cfgetispeed(tp);               /* save the original setting */
 
722
        ospeed = cfgetospeed(tp);
 
723
    } else
 
724
        ospeed = ispeed = op->speeds[FIRST_SPEED];
710
725
 
711
726
    /*
712
727
     * Initial termios settings: 8-bit characters, raw-mode, blocking i/o.
717
732
    /* flush input and output queues, important for modems! */
718
733
    (void) tcflush(0, TCIOFLUSH);
719
734
 
720
 
    tp->c_cflag = CS8 | HUPCL | CREAD;
721
 
    cfsetispeed(tp, speed);
722
 
    cfsetospeed(tp, speed);
 
735
    tp->c_iflag = tp->c_lflag = tp->c_oflag = 0;
 
736
 
 
737
    if (!(op->flags & F_KEEPCFLAGS))
 
738
        tp->c_cflag = CS8 | HUPCL | CREAD | (tp->c_cflag & CLOCAL);
 
739
 
 
740
    /* Note that the speed is stored in the c_cflag termios field, so we have
 
741
     * set the speed always when the cflag se reseted.
 
742
     */
 
743
    cfsetispeed(tp, ispeed);
 
744
    cfsetospeed(tp, ospeed);
 
745
 
723
746
    if (op->flags & F_LOCAL) {
724
747
        tp->c_cflag |= CLOCAL;
725
748
    }
726
749
 
727
 
    tp->c_iflag = tp->c_lflag = tp->c_oflag = 0;
728
750
#ifdef HAVE_STRUCT_TERMIOS_C_LINE
729
751
    tp->c_line = 0;
730
752
#endif
824
846
    (void) uname(&uts);
825
847
#endif
826
848
 
827
 
    (void) write(1, "\r\n", 2);                 /* start a new line */
 
849
    ignore_result( write(1, "\r\n", 2) );                       /* start a new line */
828
850
#ifdef  ISSUE                                   /* optional: show /etc/issue */
829
851
    if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) {
830
852
        oflag = tp->c_oflag;                    /* save current setting */
900
922
                  case 'd':
901
923
                  case 't':
902
924
                    {
903
 
                      /* TODO: use nl_langinfo() */
904
 
                      char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
905
 
                                          "Fri", "Sat" };
906
 
                      char *month[] = { "Jan", "Feb", "Mar", "Apr", "May",
907
 
                                        "Jun", "Jul", "Aug", "Sep", "Oct",
908
 
                                        "Nov", "Dec" };
909
925
                      time_t now;
910
926
                      struct tm *tm;
911
927
 
914
930
 
915
931
                      if (c == 'd')
916
932
                        (void) printf ("%s %s %d  %d",
917
 
                                weekday[tm->tm_wday], month[tm->tm_mon],
918
 
                                tm->tm_mday, 
 
933
                                nl_langinfo(ABDAY_1 + tm->tm_wday),
 
934
                                nl_langinfo(ABMON_1 + tm->tm_mon),
 
935
                                tm->tm_mday,
919
936
                                tm->tm_year < 70 ? tm->tm_year + 2000 :
920
937
                                tm->tm_year + 1900);
921
938
                      else
922
939
                        (void) printf ("%02d:%02d:%02d",
923
940
                                tm->tm_hour, tm->tm_min, tm->tm_sec);
924
 
                      
925
941
                      break;
926
942
                    }
927
943
 
973
989
    {
974
990
        char hn[MAXHOSTNAMELEN+1];
975
991
        if (gethostname(hn, sizeof(hn)) == 0)
976
 
            write(1, hn, strlen(hn));
 
992
            ignore_result( write(1, hn, strlen(hn)) );
977
993
    }
978
 
    (void) write(1, LOGIN, sizeof(LOGIN) - 1);  /* always show login prompt */
 
994
    ignore_result( write(1, LOGIN, sizeof(LOGIN) - 1) );        /* always show login prompt */
979
995
}
980
996
 
981
997
/* next_speed - select next baud rate */
984
1000
     struct termios *tp;
985
1001
     struct options *op;
986
1002
{
987
 
    static int baud_index = FIRST_SPEED;/* current speed index */
988
 
 
989
 
    baud_index = (baud_index + 1) % op->numspeed;
 
1003
    static int baud_index = -1;
 
1004
 
 
1005
    if (baud_index == -1)
 
1006
        /*
 
1007
         * if the F_KEEPSPEED flags is set then the FIRST_SPEED is not
 
1008
         * tested yet (see termio_init()).
 
1009
         */
 
1010
        baud_index = (op->flags & F_KEEPSPEED) ? FIRST_SPEED :
 
1011
                                                 1 % op->numspeed;
 
1012
    else
 
1013
        baud_index = (baud_index + 1) % op->numspeed;
 
1014
 
990
1015
    cfsetispeed(tp, op->speeds[baud_index]);
991
1016
    cfsetospeed(tp, op->speeds[baud_index]);
992
1017
    (void) tcsetattr(0, TCSANOW, tp);
1037
1062
 
1038
1063
            if (read(0, &c, 1) < 1) {
1039
1064
                if (errno == EINTR || errno == EIO)
1040
 
                    exit(0);
 
1065
                    exit(EXIT_SUCCESS);
1041
1066
                error(_("%s: read: %m"), op->tty);
1042
1067
            }
1043
1068
            /* Do BREAK handling elsewhere. */
1044
1069
 
1045
1070
            if ((c == 0) && op->numspeed > 1)
1046
 
                return (0);
 
1071
                return EXIT_SUCCESS;
1047
1072
            /* Do parity bit handling. */
1048
1073
 
1049
1074
            if (op->eightbits) {
1067
1092
            case '#':
1068
1093
                cp->erase = ascval;             /* set erase character */
1069
1094
                if (bp > logname) {
1070
 
                    (void) write(1, erase[cp->parity], 3);
 
1095
                    ignore_result( write(1, erase[cp->parity], 3) );
1071
1096
                    bp--;
1072
1097
                }
1073
1098
                break;
1075
1100
            case '@':
1076
1101
                cp->kill = ascval;              /* set kill character */
1077
1102
                while (bp > logname) {
1078
 
                    (void) write(1, erase[cp->parity], 3);
 
1103
                    ignore_result( write(1, erase[cp->parity], 3) );
1079
1104
                    bp--;
1080
1105
                }
1081
1106
                break;
1082
1107
            case CTL('D'):
1083
 
                exit(0);
 
1108
                exit(EXIT_SUCCESS);
1084
1109
            default:
1085
1110
                if (!isascii(ascval) || !isprint(ascval)) {
1086
1111
                     /* ignore garbage characters */ ;
1087
1112
                } else if (bp - logname >= sizeof(logname) - 1) {
1088
1113
                    error(_("%s: input overrun"), op->tty);
1089
1114
                } else {
1090
 
                    (void) write(1, &c, 1);     /* echo the character */
 
1115
                    ignore_result( write(1, &c, 1) );   /* echo the character */
1091
1116
                    *bp++ = ascval;             /* and store it */
1092
1117
                }
1093
1118
                break;
1100
1125
            if (isupper(*bp))
1101
1126
                *bp = tolower(*bp);             /* map name to lower case */
1102
1127
    }
1103
 
    return (logname);
 
1128
    return logname;
1104
1129
}
1105
1130
 
1106
1131
/* termio_final - set the final tty mode bits */
1188
1213
 
1189
1214
    for (capslock = 0; *s; s++) {
1190
1215
        if (islower(*s))
1191
 
            return (0);
 
1216
            return EXIT_SUCCESS;
1192
1217
        if (capslock == 0)
1193
1218
            capslock = isupper(*s);
1194
1219
    }
1195
 
    return (capslock);
 
1220
    return capslock;
1196
1221
}
1197
1222
 
1198
1223
/* bcode - convert speed string to speed code; return 0 on failure */
1205
1230
 
1206
1231
    for (sp = speedtab; sp->speed; sp++)
1207
1232
        if (sp->speed == speed)
1208
 
            return (sp->code);
1209
 
    return (0);
 
1233
            return sp->code;
 
1234
    return 0;
1210
1235
}
1211
1236
 
1212
1237
/* usage - explain */
1213
1238
 
1214
 
void
1215
 
usage()
 
1239
void __attribute__((__noreturn__)) usage(void)
1216
1240
{
1217
 
    fprintf(stderr, _("Usage: %s [-8hiLmUw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] baud_rate,... line [termtype]\nor\t[-hiLmw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] line baud_rate,... [termtype]\n"), progname);
1218
 
    exit(1);
 
1241
    fprintf(stderr, _("Usage: %s [-8hiLmsUw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] baud_rate,... line [termtype]\nor\t[-hiLmw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] line baud_rate,... [termtype]\n"), progname);
 
1242
    exit(EXIT_FAILURE);
1219
1243
}
1220
1244
 
1221
1245
/* error - report errors to console or syslog; only understands %s and %m */
1284
1308
    /* Terminate with CR-LF since the console mode is unknown. */
1285
1309
    (void) strcat(bp, "\r\n");
1286
1310
    if ((fd = open("/dev/console", 1)) >= 0) {
1287
 
        (void) write(fd, buf, strlen(buf));
 
1311
        ignore_result( write(fd, buf, strlen(buf)) );
1288
1312
        (void) close(fd);
1289
1313
    }
1290
1314
#endif