home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / permissions / part02 < prev    next >
Encoding:
Text File  |  1992-03-22  |  44.2 KB  |  2,273 lines

  1. Newsgroups: comp.sources.unix
  2. From: deraadt@cpsc.ucalgary.ca (Theo Deraadt)
  3. Subject: v25i153: permissions - access control library for YP/NIS environments, Part02/03
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: deraadt@cpsc.ucalgary.ca (Theo Deraadt)
  8. Posting-Number: Volume 25, Issue 153
  9. Archive-Name: permissions/part02
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 2 (of 3)."
  18. # Contents:  in.ftpd/ftpcmd.y in.ftpd/glob.c login/login.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Tue Mar 10 23:11:21 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'in.ftpd/ftpcmd.y' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'in.ftpd/ftpcmd.y'\"
  23. else
  24. echo shar: Extracting \"'in.ftpd/ftpcmd.y'\" \(16052 characters\)
  25. sed "s/^X//" >'in.ftpd/ftpcmd.y' <<'END_OF_FILE'
  26. X/*
  27. X * Copyright (c) 1985, 1988 Regents of the University of California.
  28. X * All rights reserved.
  29. X *
  30. X * Redistribution and use in source and binary forms are permitted
  31. X * provided that the above copyright notice and this paragraph are
  32. X * duplicated in all such forms and that any documentation,
  33. X * advertising materials, and other materials related to such
  34. X * distribution and use acknowledge that the software was developed
  35. X * by the University of California, Berkeley.  The name of the
  36. X * University may not be used to endorse or promote products derived
  37. X * from this software without specific prior written permission.
  38. X */
  39. X
  40. X/*
  41. X * Grammar for FTP commands.
  42. X * See RFC 765.
  43. X */
  44. X
  45. X%{
  46. X
  47. X#ifndef lint
  48. static    char sccsid[] = "@(#)ftpcmd.y 1.1 90/03/23 SMI"; /* from UCB 5.16 12/8/88 */
  49. X#endif
  50. X
  51. X#include <sys/types.h>
  52. X#include <sys/socket.h>
  53. X
  54. X#include <netinet/in.h>
  55. X
  56. X#include <arpa/ftp.h>
  57. X
  58. X#include <stdio.h>
  59. X#include <signal.h>
  60. X#include <ctype.h>
  61. X#include <pwd.h>
  62. X#include <setjmp.h>
  63. X#include <syslog.h>
  64. X
  65. extern    struct sockaddr_in data_dest;
  66. extern    int logged_in;
  67. extern    struct passwd *pw;
  68. extern    int guest;
  69. extern    int logging;
  70. extern    int type;
  71. extern    int form;
  72. extern    int debug;
  73. extern    int timeout;
  74. extern  int pdata;
  75. extern    char hostname[];
  76. extern    char *globerr;
  77. extern    int usedefault;
  78. extern  int transflag;
  79. extern  char tmpline[];
  80. char    **glob();
  81. X
  82. static    int cmd_type;
  83. static    int cmd_form;
  84. static    int cmd_bytesz;
  85. char    cbuf[512];
  86. char    *fromname;
  87. X
  88. char    *index();
  89. X%}
  90. X
  91. X%token
  92. X    A    B    C    E    F    I
  93. X    L    N    P    R    S    T
  94. X
  95. X    SP    CRLF    COMMA    STRING    NUMBER
  96. X
  97. X    USER    PASS    ACCT    REIN    QUIT    PORT
  98. X    PASV    TYPE    STRU    MODE    RETR    STOR
  99. X    APPE    MLFL    MAIL    MSND    MSOM    MSAM
  100. X    MRSQ    MRCP    ALLO    REST    RNFR    RNTO
  101. X    ABOR    DELE    CWD    LIST    NLST    SITE
  102. X    STAT    HELP    NOOP    XMKD    XRMD    XPWD
  103. X    XCUP    STOU
  104. X
  105. X    LEXERR
  106. X
  107. X%start    cmd_list
  108. X
  109. X%%
  110. X
  111. cmd_list:    /* empty */
  112. X    |    cmd_list cmd
  113. X        = {
  114. X            fromname = (char *) 0;
  115. X        }
  116. X    |    cmd_list rcmd
  117. X    ;
  118. X
  119. cmd:        USER SP username CRLF
  120. X        = {
  121. X            user((char *) $3);
  122. X            free((char *) $3);
  123. X        }
  124. X    |    PASS SP password CRLF
  125. X        = {
  126. X            pass((char *) $3);
  127. X            free((char *) $3);
  128. X        }
  129. X    |    PORT SP host_port CRLF
  130. X        = {
  131. X            usedefault = 0;
  132. X            if (pdata >= 0) {
  133. X                (void) close(pdata);
  134. X                pdata = -1;
  135. X            }
  136. X            reply(200, "PORT command successful.");
  137. X        }
  138. X    |    PASV CRLF
  139. X        = {
  140. X            passive();
  141. X        }
  142. X    |    TYPE SP type_code CRLF
  143. X        = {
  144. X            switch (cmd_type) {
  145. X
  146. X            case TYPE_A:
  147. X                if (cmd_form == FORM_N) {
  148. X                    reply(200, "Type set to A.");
  149. X                    type = cmd_type;
  150. X                    form = cmd_form;
  151. X                } else
  152. X                    reply(504, "Form must be N.");
  153. X                break;
  154. X
  155. X            case TYPE_E:
  156. X                reply(504, "Type E not implemented.");
  157. X                break;
  158. X
  159. X            case TYPE_I:
  160. X                reply(200, "Type set to I.");
  161. X                type = cmd_type;
  162. X                break;
  163. X
  164. X            case TYPE_L:
  165. X                if (cmd_bytesz == 8) {
  166. X                    reply(200,
  167. X                        "Type set to L (byte size 8).");
  168. X                    type = cmd_type;
  169. X                } else
  170. X                    reply(504, "Byte size must be 8.");
  171. X            }
  172. X        }
  173. X    |    STRU SP struct_code CRLF
  174. X        = {
  175. X            switch ($3) {
  176. X
  177. X            case STRU_F:
  178. X                reply(200, "STRU F ok.");
  179. X                break;
  180. X
  181. X            default:
  182. X                reply(504, "Unimplemented STRU type.");
  183. X            }
  184. X        }
  185. X    |    MODE SP mode_code CRLF
  186. X        = {
  187. X            switch ($3) {
  188. X
  189. X            case MODE_S:
  190. X                reply(200, "MODE S ok.");
  191. X                break;
  192. X
  193. X            default:
  194. X                reply(502, "Unimplemented MODE type.");
  195. X            }
  196. X        }
  197. X    |    ALLO SP NUMBER CRLF
  198. X        = {
  199. X            reply(202, "ALLO command ignored.");
  200. X        }
  201. X    |    RETR check_login SP pathname CRLF
  202. X        = {
  203. X            if ($2 && $4 != NULL)
  204. X                retrieve((char *) 0, (char *) $4);
  205. X            if ($4 != NULL)
  206. X                free((char *) $4);
  207. X        }
  208. X    |    STOR check_login SP pathname CRLF
  209. X        = {
  210. X            if ($2 && $4 != NULL)
  211. X                store((char *) $4, "w", 0);
  212. X            if ($4 != NULL)
  213. X                free((char *) $4);
  214. X        }
  215. X    |    APPE check_login SP pathname CRLF
  216. X        = {
  217. X            if ($2 && $4 != NULL)
  218. X                store((char *) $4, "a", 0);
  219. X            if ($4 != NULL)
  220. X                free((char *) $4);
  221. X        }
  222. X    |    NLST check_login CRLF
  223. X        = {
  224. X            if ($2)
  225. X                retrieve("/bin/ls", "");
  226. X        }
  227. X    |    NLST check_login SP pathname CRLF
  228. X        = {
  229. X            if ($2 && $4 != NULL)
  230. X                retrieve("/bin/ls %s", (char *) $4);
  231. X            if ($4 != NULL)
  232. X                free((char *) $4);
  233. X        }
  234. X    |    LIST check_login CRLF
  235. X        = {
  236. X            if ($2)
  237. X                retrieve("/bin/ls -lg", "");
  238. X        }
  239. X    |    LIST check_login SP pathname CRLF
  240. X        = {
  241. X            if ($2 && $4 != NULL)
  242. X                retrieve("/bin/ls -lg %s", (char *) $4);
  243. X            if ($4 != NULL)
  244. X                free((char *) $4);
  245. X        }
  246. X    |    DELE check_login SP pathname CRLF
  247. X        = {
  248. X            if ($2 && $4 != NULL)
  249. X                delete((char *) $4);
  250. X            if ($4 != NULL)
  251. X                free((char *) $4);
  252. X        }
  253. X    |    RNTO SP pathname CRLF
  254. X        = {
  255. X            if (fromname) {
  256. X                renamecmd(fromname, (char *) $3);
  257. X                free(fromname);
  258. X                fromname = (char *) 0;
  259. X            } else {
  260. X                reply(503, "Bad sequence of commands.");
  261. X            }
  262. X            free((char *) $3);
  263. X        }
  264. X    |    ABOR CRLF
  265. X        = {
  266. X            reply(225, "ABOR command successful.");
  267. X        }
  268. X    |    CWD check_login CRLF
  269. X        = {
  270. X            if ($2)
  271. X                cwd(pw->pw_dir);
  272. X        }
  273. X    |    CWD check_login SP pathname CRLF
  274. X        = {
  275. X            if ($2 && $4 != NULL)
  276. X                cwd((char *) $4);
  277. X            if ($4 != NULL)
  278. X                free((char *) $4);
  279. X        }
  280. X    |    HELP CRLF
  281. X        = {
  282. X            help((char *) 0);
  283. X        }
  284. X    |    HELP SP STRING CRLF
  285. X        = {
  286. X            help((char *) $3);
  287. X        }
  288. X    |    NOOP CRLF
  289. X        = {
  290. X            reply(200, "NOOP command successful.");
  291. X        }
  292. X    |    XMKD check_login SP pathname CRLF
  293. X        = {
  294. X            if ($2 && $4 != NULL)
  295. X                makedir((char *) $4);
  296. X            if ($4 != NULL)
  297. X                free((char *) $4);
  298. X        }
  299. X    |    XRMD check_login SP pathname CRLF
  300. X        = {
  301. X            if ($2 && $4 != NULL)
  302. X                removedir((char *) $4);
  303. X            if ($4 != NULL)
  304. X                free((char *) $4);
  305. X        }
  306. X    |    XPWD check_login CRLF
  307. X        = {
  308. X            if ($2)
  309. X                pwd();
  310. X        }
  311. X    |    XCUP check_login CRLF
  312. X        = {
  313. X            if ($2)
  314. X                cwd("..");
  315. X        }
  316. X    |    STOU check_login SP pathname CRLF
  317. X        = {
  318. X            if ($2 && $4 != NULL)
  319. X                store((char *) $4, "w", 1);
  320. X            if ($4 != NULL)
  321. X                free((char *) $4);
  322. X        }
  323. X    |    QUIT CRLF
  324. X        = {
  325. X            reply(221, "Goodbye.");
  326. X            dologout(0);
  327. X        }
  328. X    |    error CRLF
  329. X        = {
  330. X            yyerrok;
  331. X        }
  332. X    ;
  333. X
  334. rcmd:        RNFR check_login SP pathname CRLF
  335. X        = {
  336. X            char *renamefrom();
  337. X
  338. X            if ($2 && $4) {
  339. X                fromname = renamefrom((char *) $4);
  340. X                if (fromname == (char *) 0 && $4) {
  341. X                    free((char *) $4);
  342. X                }
  343. X            }
  344. X        }
  345. X    ;
  346. X        
  347. username:    STRING
  348. X    ;
  349. X
  350. password:    /* empty */
  351. X        = {
  352. X            $$ = (int) "";
  353. X        }
  354. X    |    STRING
  355. X    ;
  356. X
  357. byte_size:    NUMBER
  358. X    ;
  359. X
  360. host_port:    NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA 
  361. X        NUMBER COMMA NUMBER
  362. X        = {
  363. X            register char *a, *p;
  364. X
  365. X            a = (char *)&data_dest.sin_addr;
  366. X            a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7;
  367. X            p = (char *)&data_dest.sin_port;
  368. X            p[0] = $9; p[1] = $11;
  369. X            data_dest.sin_family = AF_INET;
  370. X        }
  371. X    ;
  372. X
  373. form_code:    N
  374. X    = {
  375. X        $$ = FORM_N;
  376. X    }
  377. X    |    T
  378. X    = {
  379. X        $$ = FORM_T;
  380. X    }
  381. X    |    C
  382. X    = {
  383. X        $$ = FORM_C;
  384. X    }
  385. X    ;
  386. X
  387. type_code:    A
  388. X    = {
  389. X        cmd_type = TYPE_A;
  390. X        cmd_form = FORM_N;
  391. X    }
  392. X    |    A SP form_code
  393. X    = {
  394. X        cmd_type = TYPE_A;
  395. X        cmd_form = $3;
  396. X    }
  397. X    |    E
  398. X    = {
  399. X        cmd_type = TYPE_E;
  400. X        cmd_form = FORM_N;
  401. X    }
  402. X    |    E SP form_code
  403. X    = {
  404. X        cmd_type = TYPE_E;
  405. X        cmd_form = $3;
  406. X    }
  407. X    |    I
  408. X    = {
  409. X        cmd_type = TYPE_I;
  410. X    }
  411. X    |    L
  412. X    = {
  413. X        cmd_type = TYPE_L;
  414. X        cmd_bytesz = 8;
  415. X    }
  416. X    |    L SP byte_size
  417. X    = {
  418. X        cmd_type = TYPE_L;
  419. X        cmd_bytesz = $3;
  420. X    }
  421. X    /* this is for a bug in the BBN ftp */
  422. X    |    L byte_size
  423. X    = {
  424. X        cmd_type = TYPE_L;
  425. X        cmd_bytesz = $2;
  426. X    }
  427. X    ;
  428. X
  429. struct_code:    F
  430. X    = {
  431. X        $$ = STRU_F;
  432. X    }
  433. X    |    R
  434. X    = {
  435. X        $$ = STRU_R;
  436. X    }
  437. X    |    P
  438. X    = {
  439. X        $$ = STRU_P;
  440. X    }
  441. X    ;
  442. X
  443. mode_code:    S
  444. X    = {
  445. X        $$ = MODE_S;
  446. X    }
  447. X    |    B
  448. X    = {
  449. X        $$ = MODE_B;
  450. X    }
  451. X    |    C
  452. X    = {
  453. X        $$ = MODE_C;
  454. X    }
  455. X    ;
  456. X
  457. pathname:    pathstring
  458. X    = {
  459. X        /*
  460. X         * Problem: this production is used for all pathname
  461. X         * processing, but only gives a 550 error reply.
  462. X         * This is a valid reply in some cases but not in others.
  463. X         */
  464. X        if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) {
  465. X            $$ = (int)*glob((char *) $1);
  466. X            if (globerr != NULL) {
  467. X                reply(550, globerr);
  468. X                $$ = NULL;
  469. X            }
  470. X            free((char *) $1);
  471. X        } else
  472. X            $$ = $1;
  473. X    }
  474. X    ;
  475. X
  476. pathstring:    STRING
  477. X    ;
  478. X
  479. check_login:    /* empty */
  480. X    = {
  481. X        if (logged_in)
  482. X            $$ = 1;
  483. X        else {
  484. X            reply(530, "Please login with USER and PASS.");
  485. X            $$ = 0;
  486. X        }
  487. X    }
  488. X    ;
  489. X
  490. X%%
  491. X
  492. extern jmp_buf errcatch;
  493. X
  494. X#define    CMD    0    /* beginning of command */
  495. X#define    ARGS    1    /* expect miscellaneous arguments */
  496. X#define    STR1    2    /* expect SP followed by STRING */
  497. X#define    STR2    3    /* expect STRING */
  498. X#define    OSTR    4    /* optional SP then STRING */
  499. X#define    ZSTR1    5    /* SP then optional STRING */
  500. X#define    ZSTR2    6    /* optional STRING after SP */
  501. X
  502. struct tab {
  503. X    char    *name;
  504. X    short    token;
  505. X    short    state;
  506. X    short    implemented;    /* 1 if command is implemented */
  507. X    char    *help;
  508. X};
  509. X
  510. struct tab cmdtab[] = {        /* In order defined in RFC 765 */
  511. X    { "USER", USER, STR1, 1,    "<sp> username" },
  512. X    { "PASS", PASS, ZSTR1, 1,    "<sp> password" },
  513. X    { "ACCT", ACCT, STR1, 0,    "(specify account)" },
  514. X    { "REIN", REIN, ARGS, 0,    "(reinitialize server state)" },
  515. X    { "QUIT", QUIT, ARGS, 1,    "(terminate service)", },
  516. X    { "PORT", PORT, ARGS, 1,    "<sp> b0, b1, b2, b3, b4" },
  517. X    { "PASV", PASV, ARGS, 1,    "(set server in passive mode)" },
  518. X    { "TYPE", TYPE, ARGS, 1,    "<sp> [ A | E | I | L ]" },
  519. X    { "STRU", STRU, ARGS, 1,    "(specify file structure)" },
  520. X    { "MODE", MODE, ARGS, 1,    "(specify transfer mode)" },
  521. X    { "RETR", RETR, STR1, 1,    "<sp> file-name" },
  522. X    { "STOR", STOR, STR1, 1,    "<sp> file-name" },
  523. X    { "APPE", APPE, STR1, 1,    "<sp> file-name" },
  524. X    { "MLFL", MLFL, OSTR, 0,    "(mail file)" },
  525. X    { "MAIL", MAIL, OSTR, 0,    "(mail to user)" },
  526. X    { "MSND", MSND, OSTR, 0,    "(mail send to terminal)" },
  527. X    { "MSOM", MSOM, OSTR, 0,    "(mail send to terminal or mailbox)" },
  528. X    { "MSAM", MSAM, OSTR, 0,    "(mail send to terminal and mailbox)" },
  529. X    { "MRSQ", MRSQ, OSTR, 0,    "(mail recipient scheme question)" },
  530. X    { "MRCP", MRCP, STR1, 0,    "(mail recipient)" },
  531. X    { "ALLO", ALLO, ARGS, 1,    "allocate storage (vacuously)" },
  532. X    { "REST", REST, STR1, 0,    "(restart command)" },
  533. X    { "RNFR", RNFR, STR1, 1,    "<sp> file-name" },
  534. X    { "RNTO", RNTO, STR1, 1,    "<sp> file-name" },
  535. X    { "ABOR", ABOR, ARGS, 1,    "(abort operation)" },
  536. X    { "DELE", DELE, STR1, 1,    "<sp> file-name" },
  537. X    { "CWD",  CWD,  OSTR, 1,    "[ <sp> directory-name ]" },
  538. X    { "XCWD", CWD,    OSTR, 1,    "[ <sp> directory-name ]" },
  539. X    { "LIST", LIST, OSTR, 1,    "[ <sp> path-name ]" },
  540. X    { "NLST", NLST, OSTR, 1,    "[ <sp> path-name ]" },
  541. X    { "SITE", SITE, STR1, 0,    "(get site parameters)" },
  542. X    { "STAT", STAT, OSTR, 0,    "(get server status)" },
  543. X    { "HELP", HELP, OSTR, 1,    "[ <sp> <string> ]" },
  544. X    { "NOOP", NOOP, ARGS, 1,    "" },
  545. X    { "MKD",  XMKD, STR1, 1,    "<sp> path-name" },
  546. X    { "XMKD", XMKD, STR1, 1,    "<sp> path-name" },
  547. X    { "RMD",  XRMD, STR1, 1,    "<sp> path-name" },
  548. X    { "XRMD", XRMD, STR1, 1,    "<sp> path-name" },
  549. X    { "PWD",  XPWD, ARGS, 1,    "(return current directory)" },
  550. X    { "XPWD", XPWD, ARGS, 1,    "(return current directory)" },
  551. X    { "CDUP", XCUP, ARGS, 1,    "(change to parent directory)" },
  552. X    { "XCUP", XCUP, ARGS, 1,    "(change to parent directory)" },
  553. X    { "STOU", STOU, STR1, 1,    "<sp> file-name" },
  554. X    { NULL,   0,    0,    0,    0 }
  555. X};
  556. X
  557. struct tab *
  558. lookup(cmd)
  559. X    char *cmd;
  560. X{
  561. X    register struct tab *p;
  562. X
  563. X    for (p = cmdtab; p->name != NULL; p++)
  564. X        if (strcmp(cmd, p->name) == 0)
  565. X            return (p);
  566. X    return (0);
  567. X}
  568. X
  569. X#include <arpa/telnet.h>
  570. X
  571. X/*
  572. X * getline - a hacked up version of fgets to ignore TELNET escape codes.
  573. X */
  574. char *
  575. getline(s, n, iop)
  576. X    char *s;
  577. X    register FILE *iop;
  578. X{
  579. X    register c;
  580. X    register char *cs;
  581. X
  582. X    cs = s;
  583. X/* tmpline may contain saved command from urgent mode interruption */
  584. X    for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
  585. X        *cs++ = tmpline[c];
  586. X        if (tmpline[c] == '\n') {
  587. X            *cs++ = '\0';
  588. X            if (debug)
  589. X                syslog(LOG_DEBUG, "command: %s", s);
  590. X            tmpline[0] = '\0';
  591. X            return(s);
  592. X        }
  593. X        if (c == 0)
  594. X            tmpline[0] = '\0';
  595. X    }
  596. X    while ((c = getc(iop)) != EOF) {
  597. X        c &= 0377;
  598. X        if (c == IAC) {
  599. X            if ((c = getc(iop)) != EOF) {
  600. X            c &= 0377;
  601. X            switch (c) {
  602. X            case WILL:
  603. X            case WONT:
  604. X                c = getc(iop);
  605. X                printf("%c%c%c", IAC, DONT, 0377&c);
  606. X                (void) fflush(stdout);
  607. X                continue;
  608. X            case DO:
  609. X            case DONT:
  610. X                c = getc(iop);
  611. X                printf("%c%c%c", IAC, WONT, 0377&c);
  612. X                (void) fflush(stdout);
  613. X                continue;
  614. X            case IAC:
  615. X                break;
  616. X            default:
  617. X                continue;    /* ignore command */
  618. X            }
  619. X            }
  620. X        }
  621. X        *cs++ = c;
  622. X        if (--n <= 0 || c == '\n')
  623. X            break;
  624. X    }
  625. X    if (c == EOF && cs == s)
  626. X        return (NULL);
  627. X    *cs++ = '\0';
  628. X    if (debug)
  629. X        syslog(LOG_DEBUG, "command: %s", s);
  630. X    return (s);
  631. X}
  632. X
  633. static int
  634. toolong()
  635. X{
  636. X    time_t now;
  637. X    extern char *ctime();
  638. X    extern time_t time();
  639. X
  640. X    reply(421,
  641. X      "Timeout (%d seconds): closing control connection.", timeout);
  642. X    (void) time(&now);
  643. X    if (logging) {
  644. X        syslog(LOG_INFO,
  645. X            "User %s timed out after %d seconds at %s",
  646. X            (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
  647. X    }
  648. X    dologout(1);
  649. X}
  650. X
  651. yylex()
  652. X{
  653. X    static int cpos, state;
  654. X    register char *cp;
  655. X    register struct tab *p;
  656. X    int n;
  657. X    char c, *strpbrk();
  658. X
  659. X    for (;;) {
  660. X        switch (state) {
  661. X
  662. X        case CMD:
  663. X            (void) signal(SIGALRM, toolong);
  664. X            (void) alarm((unsigned) timeout);
  665. X            if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
  666. X                reply(221, "You could at least say goodbye.");
  667. X                dologout(0);
  668. X            }
  669. X            (void) alarm(0);
  670. X            if ((cp = index(cbuf, '\r'))) {
  671. X                *cp++ = '\n';
  672. X                *cp = '\0';
  673. X            }
  674. X            if ((cp = strpbrk(cbuf, " \n")))
  675. X                cpos = cp - cbuf;
  676. X            if (cpos == 0)
  677. X                cpos = 4;
  678. X            c = cbuf[cpos];
  679. X            cbuf[cpos] = '\0';
  680. X            upper(cbuf);
  681. X            p = lookup(cbuf);
  682. X            cbuf[cpos] = c;
  683. X            if (p != 0) {
  684. X                if (p->implemented == 0) {
  685. X                    nack(p->name);
  686. X                    longjmp(errcatch,0);
  687. X                    /* NOTREACHED */
  688. X                }
  689. X                state = p->state;
  690. X                yylval = (int) p->name;
  691. X                return (p->token);
  692. X            }
  693. X            break;
  694. X
  695. X        case OSTR:
  696. X            if (cbuf[cpos] == '\n') {
  697. X                state = CMD;
  698. X                return (CRLF);
  699. X            }
  700. X            /* FALLTHROUGH */
  701. X
  702. X        case STR1:
  703. X        case ZSTR1:
  704. X            if (cbuf[cpos] == ' ') {
  705. X                cpos++;
  706. X                state = state == OSTR ? STR2 : ++state;
  707. X                return (SP);
  708. X            }
  709. X            break;
  710. X
  711. X        case ZSTR2:
  712. X            if (cbuf[cpos] == '\n') {
  713. X                state = CMD;
  714. X                return (CRLF);
  715. X            }
  716. X            /* FALL THRU */
  717. X
  718. X        case STR2:
  719. X            cp = &cbuf[cpos];
  720. X            n = strlen(cp);
  721. X            cpos += n - 1;
  722. X            /*
  723. X             * Make sure the string is nonempty and \n terminated.
  724. X             */
  725. X            if (n > 1 && cbuf[cpos] == '\n') {
  726. X                cbuf[cpos] = '\0';
  727. X                yylval = copy(cp);
  728. X                cbuf[cpos] = '\n';
  729. X                state = ARGS;
  730. X                return (STRING);
  731. X            }
  732. X            break;
  733. X
  734. X        case ARGS:
  735. X            if (isdigit(cbuf[cpos])) {
  736. X                cp = &cbuf[cpos];
  737. X                while (isdigit(cbuf[++cpos]))
  738. X                    ;
  739. X                c = cbuf[cpos];
  740. X                cbuf[cpos] = '\0';
  741. X                yylval = atoi(cp);
  742. X                cbuf[cpos] = c;
  743. X                return (NUMBER);
  744. X            }
  745. X            switch (cbuf[cpos++]) {
  746. X
  747. X            case '\n':
  748. X                state = CMD;
  749. X                return (CRLF);
  750. X
  751. X            case ' ':
  752. X                return (SP);
  753. X
  754. X            case ',':
  755. X                return (COMMA);
  756. X
  757. X            case 'A':
  758. X            case 'a':
  759. X                return (A);
  760. X
  761. X            case 'B':
  762. X            case 'b':
  763. X                return (B);
  764. X
  765. X            case 'C':
  766. X            case 'c':
  767. X                return (C);
  768. X
  769. X            case 'E':
  770. X            case 'e':
  771. X                return (E);
  772. X
  773. X            case 'F':
  774. X            case 'f':
  775. X                return (F);
  776. X
  777. X            case 'I':
  778. X            case 'i':
  779. X                return (I);
  780. X
  781. X            case 'L':
  782. X            case 'l':
  783. X                return (L);
  784. X
  785. X            case 'N':
  786. X            case 'n':
  787. X                return (N);
  788. X
  789. X            case 'P':
  790. X            case 'p':
  791. X                return (P);
  792. X
  793. X            case 'R':
  794. X            case 'r':
  795. X                return (R);
  796. X
  797. X            case 'S':
  798. X            case 's':
  799. X                return (S);
  800. X
  801. X            case 'T':
  802. X            case 't':
  803. X                return (T);
  804. X
  805. X            }
  806. X            break;
  807. X
  808. X        default:
  809. X            fatal("Unknown state in scanner.");
  810. X        }
  811. X        yyerror((char *) 0);
  812. X        state = CMD;
  813. X        longjmp(errcatch,0);
  814. X    }
  815. X}
  816. X
  817. upper(s)
  818. X    register char *s;
  819. X{
  820. X    while (*s != '\0') {
  821. X        if (islower(*s))
  822. X            *s = toupper(*s);
  823. X        s++;
  824. X    }
  825. X}
  826. X
  827. copy(s)
  828. X    char *s;
  829. X{
  830. X    char *p;
  831. X    extern char *malloc(), *strcpy();
  832. X
  833. X    p = malloc((unsigned) strlen(s) + 1);
  834. X    if (p == NULL)
  835. X        fatal("Ran out of memory.");
  836. X    (void) strcpy(p, s);
  837. X    return ((int)p);
  838. X}
  839. X
  840. help(s)
  841. X    char *s;
  842. X{
  843. X    register struct tab *c;
  844. X    register int width, NCMDS;
  845. X
  846. X    width = 0, NCMDS = 0;
  847. X    for (c = cmdtab; c->name != NULL; c++) {
  848. X        int len = strlen(c->name) + 1;
  849. X
  850. X        if (len > width)
  851. X            width = len;
  852. X        NCMDS++;
  853. X    }
  854. X    width = (width + 8) &~ 7;
  855. X    if (s == 0) {
  856. X        register int i, j, w;
  857. X        int columns, lines;
  858. X
  859. X        lreply(214,
  860. X      "The following commands are recognized (* =>'s unimplemented).");
  861. X        columns = 76 / width;
  862. X        if (columns == 0)
  863. X            columns = 1;
  864. X        lines = (NCMDS + columns - 1) / columns;
  865. X        for (i = 0; i < lines; i++) {
  866. X            printf("   ");
  867. X            for (j = 0; j < columns; j++) {
  868. X                c = cmdtab + j * lines + i;
  869. X                printf("%s%c", c->name,
  870. X                    c->implemented ? ' ' : '*');
  871. X                if (c + lines >= &cmdtab[NCMDS])
  872. X                    break;
  873. X                w = strlen(c->name) + 1;
  874. X                while (w < width) {
  875. X                    putchar(' ');
  876. X                    w++;
  877. X                }
  878. X            }
  879. X            printf("\r\n");
  880. X        }
  881. X        (void) fflush(stdout);
  882. X        reply(214, "Direct comments to bugs@Sun.COM.");
  883. X        return;
  884. X    }
  885. X    upper(s);
  886. X    c = lookup(s);
  887. X    if (c == (struct tab *)0) {
  888. X        reply(502, "Unknown command %s.", s);
  889. X        return;
  890. X    }
  891. X    if (c->implemented)
  892. X        reply(214, "Syntax: %s %s", c->name, c->help);
  893. X    else
  894. X        reply(214, "%-*s\t%s; unimplemented.", width, c->name, c->help);
  895. X}
  896. END_OF_FILE
  897. if test 16052 -ne `wc -c <'in.ftpd/ftpcmd.y'`; then
  898.     echo shar: \"'in.ftpd/ftpcmd.y'\" unpacked with wrong size!
  899. fi
  900. # end of 'in.ftpd/ftpcmd.y'
  901. fi
  902. if test -f 'in.ftpd/glob.c' -a "${1}" != "-c" ; then 
  903.   echo shar: Will not clobber existing file \"'in.ftpd/glob.c'\"
  904. else
  905. echo shar: Extracting \"'in.ftpd/glob.c'\" \(9587 characters\)
  906. sed "s/^X//" >'in.ftpd/glob.c' <<'END_OF_FILE'
  907. X/*
  908. X * Copyright (c) 1980 Regents of the University of California.
  909. X * All rights reserved.  The Berkeley software License Agreement
  910. X * specifies the terms and conditions for redistribution.
  911. X */
  912. X
  913. X#ifndef lint
  914. static char sccsid[] = "@(#)glob.c    5.2 (Berkeley) 3/7/86";
  915. X#endif not lint
  916. X
  917. X/*
  918. X * C-shell glob for random programs.
  919. X */
  920. X
  921. X#include <sys/param.h>
  922. X#include <sys/stat.h>
  923. X#include <sys/dir.h>
  924. X
  925. X#include <stdio.h>
  926. X#include <errno.h>
  927. X#include <pwd.h>
  928. X
  929. X#define    QUOTE 0200
  930. X#define    TRIM 0177
  931. X#define    eq(a,b)        (strcmp(a, b)==0)
  932. X#define    GAVSIZ        (NCARGS/6)
  933. X#define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  934. X
  935. static    char **gargv;        /* Pointer to the (stack) arglist */
  936. static    short gargc;        /* Number args in gargv */
  937. static    short gnleft;
  938. static    short gflag;
  939. static    int tglob();
  940. char    **glob();
  941. char    *globerr;
  942. char    *home;
  943. struct    passwd *getpwnam();
  944. extern    int errno;
  945. static    char *strspl(), *strend();
  946. char    *malloc(), *strcpy(), *strcat();
  947. char    **copyblk();
  948. X
  949. static    int globcnt;
  950. X
  951. char    *globchars = "`{[*?";
  952. X
  953. static    char *gpath, *gpathp, *lastgpathp;
  954. static    int globbed;
  955. static    char *entp;
  956. static    char **sortbas;
  957. X
  958. char **
  959. glob(v)
  960. X    register char *v;
  961. X{
  962. X    char agpath[BUFSIZ];
  963. X    char *agargv[GAVSIZ];
  964. X    char *vv[2];
  965. X    vv[0] = v;
  966. X    vv[1] = 0;
  967. X    gflag = 0;
  968. X    rscan(vv, tglob);
  969. X    if (gflag == 0)
  970. X        return (copyblk(vv));
  971. X
  972. X    globerr = 0;
  973. X    gpath = agpath; gpathp = gpath; *gpathp = 0;
  974. X    lastgpathp = &gpath[sizeof agpath - 2];
  975. X    ginit(agargv); globcnt = 0;
  976. X    collect(v);
  977. X    if (globcnt == 0 && (gflag&1)) {
  978. X        blkfree(gargv), gargv = 0;
  979. X        return (0);
  980. X    } else
  981. X        return (gargv = copyblk(gargv));
  982. X}
  983. X
  984. static
  985. ginit(agargv)
  986. X    char **agargv;
  987. X{
  988. X
  989. X    agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  990. X    gnleft = NCARGS - 4;
  991. X}
  992. X
  993. static
  994. collect(as)
  995. X    register char *as;
  996. X{
  997. X    if (eq(as, "{") || eq(as, "{}")) {
  998. X        Gcat(as, "");
  999. X        sort();
  1000. X    } else
  1001. X        acollect(as);
  1002. X}
  1003. X
  1004. static
  1005. acollect(as)
  1006. X    register char *as;
  1007. X{
  1008. X    register int ogargc = gargc;
  1009. X
  1010. X    gpathp = gpath; *gpathp = 0; globbed = 0;
  1011. X    expand(as);
  1012. X    if (gargc != ogargc)
  1013. X        sort();
  1014. X}
  1015. X
  1016. static
  1017. sort()
  1018. X{
  1019. X    register char **p1, **p2, *c;
  1020. X    char **Gvp = &gargv[gargc];
  1021. X
  1022. X    p1 = sortbas;
  1023. X    while (p1 < Gvp-1) {
  1024. X        p2 = p1;
  1025. X        while (++p2 < Gvp)
  1026. X            if (strcmp(*p1, *p2) > 0)
  1027. X                c = *p1, *p1 = *p2, *p2 = c;
  1028. X        p1++;
  1029. X    }
  1030. X    sortbas = Gvp;
  1031. X}
  1032. X
  1033. static
  1034. expand(as)
  1035. X    char *as;
  1036. X{
  1037. X    register char *cs;
  1038. X    register char *sgpathp, *oldcs;
  1039. X    struct stat stb;
  1040. X
  1041. X    sgpathp = gpathp;
  1042. X    cs = as;
  1043. X    if (*cs == '~' && gpathp == gpath) {
  1044. X        addpath('~');
  1045. X        for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  1046. X            addpath(*cs++);
  1047. X        if (!*cs || *cs == '/') {
  1048. X            if (gpathp != gpath + 1) {
  1049. X                *gpathp = 0;
  1050. X                if (gethdir(gpath + 1))
  1051. X                    globerr = "Unknown user name after ~";
  1052. X                (void) strcpy(gpath, gpath + 1);
  1053. X            } else
  1054. X                (void) strcpy(gpath, home);
  1055. X            gpathp = strend(gpath);
  1056. X        }
  1057. X    }
  1058. X    while (!any(*cs, globchars)) {
  1059. X        if (*cs == 0) {
  1060. X            if (!globbed)
  1061. X                Gcat(gpath, "");
  1062. X            else if (stat(gpath, &stb) >= 0) {
  1063. X                Gcat(gpath, "");
  1064. X                globcnt++;
  1065. X            }
  1066. X            goto endit;
  1067. X        }
  1068. X        addpath(*cs++);
  1069. X    }
  1070. X    oldcs = cs;
  1071. X    while (cs > as && *cs != '/')
  1072. X        cs--, gpathp--;
  1073. X    if (*cs == '/')
  1074. X        cs++, gpathp++;
  1075. X    *gpathp = 0;
  1076. X    if (*oldcs == '{') {
  1077. X        (void) execbrc(cs, ((char *)0));
  1078. X        return;
  1079. X    }
  1080. X    matchdir(cs);
  1081. endit:
  1082. X    gpathp = sgpathp;
  1083. X    *gpathp = 0;
  1084. X}
  1085. X
  1086. static
  1087. matchdir(pattern)
  1088. X    char *pattern;
  1089. X{
  1090. X    struct stat stb;
  1091. X    register struct direct *dp;
  1092. X    DIR *dirp;
  1093. X
  1094. X    dirp = opendir(gpath);
  1095. X    if (dirp == NULL) {
  1096. X        if (globbed)
  1097. X            return;
  1098. X        goto patherr2;
  1099. X    }
  1100. X    if (fstat(dirp->dd_fd, &stb) < 0)
  1101. X        goto patherr1;
  1102. X    if (!isdir(stb)) {
  1103. X        errno = ENOTDIR;
  1104. X        goto patherr1;
  1105. X    }
  1106. X    while ((dp = readdir(dirp)) != NULL) {
  1107. X        if (dp->d_ino == 0)
  1108. X            continue;
  1109. X        if (match(dp->d_name, pattern)) {
  1110. X            Gcat(gpath, dp->d_name);
  1111. X            globcnt++;
  1112. X        }
  1113. X    }
  1114. X    closedir(dirp);
  1115. X    return;
  1116. X
  1117. patherr1:
  1118. X    closedir(dirp);
  1119. patherr2:
  1120. X    globerr = "Bad directory components";
  1121. X}
  1122. X
  1123. static
  1124. execbrc(p, s)
  1125. X    char *p, *s;
  1126. X{
  1127. X    char restbuf[BUFSIZ + 2];
  1128. X    register char *pe, *pm, *pl;
  1129. X    int brclev = 0;
  1130. X    char *lm, savec, *sgpathp;
  1131. X
  1132. X    for (lm = restbuf; *p != '{'; *lm++ = *p++)
  1133. X        continue;
  1134. X    for (pe = ++p; *pe; pe++)
  1135. X    switch (*pe) {
  1136. X
  1137. X    case '{':
  1138. X        brclev++;
  1139. X        continue;
  1140. X
  1141. X    case '}':
  1142. X        if (brclev == 0)
  1143. X            goto pend;
  1144. X        brclev--;
  1145. X        continue;
  1146. X
  1147. X    case '[':
  1148. X        for (pe++; *pe && *pe != ']'; pe++)
  1149. X            continue;
  1150. X        continue;
  1151. X    }
  1152. pend:
  1153. X    brclev = 0;
  1154. X    for (pl = pm = p; pm <= pe; pm++)
  1155. X    switch (*pm & (QUOTE|TRIM)) {
  1156. X
  1157. X    case '{':
  1158. X        brclev++;
  1159. X        continue;
  1160. X
  1161. X    case '}':
  1162. X        if (brclev) {
  1163. X            brclev--;
  1164. X            continue;
  1165. X        }
  1166. X        goto doit;
  1167. X
  1168. X    case ','|QUOTE:
  1169. X    case ',':
  1170. X        if (brclev)
  1171. X            continue;
  1172. doit:
  1173. X        savec = *pm;
  1174. X        *pm = 0;
  1175. X        (void) strcpy(lm, pl);
  1176. X        (void) strcat(restbuf, pe + 1);
  1177. X        *pm = savec;
  1178. X        if (s == 0) {
  1179. X            sgpathp = gpathp;
  1180. X            expand(restbuf);
  1181. X            gpathp = sgpathp;
  1182. X            *gpathp = 0;
  1183. X        } else if (amatch(s, restbuf))
  1184. X            return (1);
  1185. X        sort();
  1186. X        pl = pm + 1;
  1187. X        if (brclev)
  1188. X            return (0);
  1189. X        continue;
  1190. X
  1191. X    case '[':
  1192. X        for (pm++; *pm && *pm != ']'; pm++)
  1193. X            continue;
  1194. X        if (!*pm)
  1195. X            pm--;
  1196. X        continue;
  1197. X    }
  1198. X    if (brclev)
  1199. X        goto doit;
  1200. X    return (0);
  1201. X}
  1202. X
  1203. static
  1204. match(s, p)
  1205. X    char *s, *p;
  1206. X{
  1207. X    register int c;
  1208. X    register char *sentp;
  1209. X    char sglobbed = globbed;
  1210. X
  1211. X    if (*s == '.' && *p != '.')
  1212. X        return (0);
  1213. X    sentp = entp;
  1214. X    entp = s;
  1215. X    c = amatch(s, p);
  1216. X    entp = sentp;
  1217. X    globbed = sglobbed;
  1218. X    return (c);
  1219. X}
  1220. X
  1221. static
  1222. amatch(s, p)
  1223. X    register char *s, *p;
  1224. X{
  1225. X    register int scc;
  1226. X    int ok, lc;
  1227. X    char *sgpathp;
  1228. X    struct stat stb;
  1229. X    int c, cc;
  1230. X
  1231. X    globbed = 1;
  1232. X    for (;;) {
  1233. X        scc = *s++ & TRIM;
  1234. X        switch (c = *p++) {
  1235. X
  1236. X        case '{':
  1237. X            return (execbrc(p - 1, s - 1));
  1238. X
  1239. X        case '[':
  1240. X            ok = 0;
  1241. X            lc = 077777;
  1242. X            while (cc = *p++) {
  1243. X                if (cc == ']') {
  1244. X                    if (ok)
  1245. X                        break;
  1246. X                    return (0);
  1247. X                }
  1248. X                if (cc == '-') {
  1249. X                    if (lc <= scc && scc <= *p++)
  1250. X                        ok++;
  1251. X                } else
  1252. X                    if (scc == (lc = cc))
  1253. X                        ok++;
  1254. X            }
  1255. X            if (cc == 0)
  1256. X                if (ok)
  1257. X                    p--;
  1258. X                else
  1259. X                    return 0;
  1260. X            continue;
  1261. X
  1262. X        case '*':
  1263. X            if (!*p)
  1264. X                return (1);
  1265. X            if (*p == '/') {
  1266. X                p++;
  1267. X                goto slash;
  1268. X            }
  1269. X            s--;
  1270. X            do {
  1271. X                if (amatch(s, p))
  1272. X                    return (1);
  1273. X            } while (*s++);
  1274. X            return (0);
  1275. X
  1276. X        case 0:
  1277. X            return (scc == 0);
  1278. X
  1279. X        default:
  1280. X            if (c != scc)
  1281. X                return (0);
  1282. X            continue;
  1283. X
  1284. X        case '?':
  1285. X            if (scc == 0)
  1286. X                return (0);
  1287. X            continue;
  1288. X
  1289. X        case '/':
  1290. X            if (scc)
  1291. X                return (0);
  1292. slash:
  1293. X            s = entp;
  1294. X            sgpathp = gpathp;
  1295. X            while (*s)
  1296. X                addpath(*s++);
  1297. X            addpath('/');
  1298. X            if (stat(gpath, &stb) == 0 && isdir(stb))
  1299. X                if (*p == 0) {
  1300. X                    Gcat(gpath, "");
  1301. X                    globcnt++;
  1302. X                } else
  1303. X                    expand(p);
  1304. X            gpathp = sgpathp;
  1305. X            *gpathp = 0;
  1306. X            return (0);
  1307. X        }
  1308. X    }
  1309. X}
  1310. X
  1311. static
  1312. Gmatch(s, p)
  1313. X    register char *s, *p;
  1314. X{
  1315. X    register int scc;
  1316. X    int ok, lc;
  1317. X    int c, cc;
  1318. X
  1319. X    for (;;) {
  1320. X        scc = *s++ & TRIM;
  1321. X        switch (c = *p++) {
  1322. X
  1323. X        case '[':
  1324. X            ok = 0;
  1325. X            lc = 077777;
  1326. X            while (cc = *p++) {
  1327. X                if (cc == ']') {
  1328. X                    if (ok)
  1329. X                        break;
  1330. X                    return (0);
  1331. X                }
  1332. X                if (cc == '-') {
  1333. X                    if (lc <= scc && scc <= *p++)
  1334. X                        ok++;
  1335. X                } else
  1336. X                    if (scc == (lc = cc))
  1337. X                        ok++;
  1338. X            }
  1339. X            if (cc == 0)
  1340. X                if (ok)
  1341. X                    p--;
  1342. X                else
  1343. X                    return 0;
  1344. X            continue;
  1345. X
  1346. X        case '*':
  1347. X            if (!*p)
  1348. X                return (1);
  1349. X            for (s--; *s; s++)
  1350. X                if (Gmatch(s, p))
  1351. X                    return (1);
  1352. X            return (0);
  1353. X
  1354. X        case 0:
  1355. X            return (scc == 0);
  1356. X
  1357. X        default:
  1358. X            if ((c & TRIM) != scc)
  1359. X                return (0);
  1360. X            continue;
  1361. X
  1362. X        case '?':
  1363. X            if (scc == 0)
  1364. X                return (0);
  1365. X            continue;
  1366. X
  1367. X        }
  1368. X    }
  1369. X}
  1370. X
  1371. static
  1372. Gcat(s1, s2)
  1373. X    register char *s1, *s2;
  1374. X{
  1375. X    register int len = strlen(s1) + strlen(s2) + 1;
  1376. X
  1377. X    if (len >= gnleft || gargc >= GAVSIZ - 1)
  1378. X        globerr = "Arguments too long";
  1379. X    else {
  1380. X        gargc++;
  1381. X        gnleft -= len;
  1382. X        gargv[gargc] = 0;
  1383. X        gargv[gargc - 1] = strspl(s1, s2);
  1384. X    }
  1385. X}
  1386. X
  1387. static
  1388. addpath(c)
  1389. X    char c;
  1390. X{
  1391. X
  1392. X    if (gpathp >= lastgpathp)
  1393. X        globerr = "Pathname too long";
  1394. X    else {
  1395. X        *gpathp++ = c;
  1396. X        *gpathp = 0;
  1397. X    }
  1398. X}
  1399. X
  1400. static
  1401. rscan(t, f)
  1402. X    register char **t;
  1403. X    int (*f)();
  1404. X{
  1405. X    register char *p, c;
  1406. X
  1407. X    while (p = *t++) {
  1408. X        if (f == tglob)
  1409. X            if (*p == '~')
  1410. X                gflag |= 2;
  1411. X            else if (eq(p, "{") || eq(p, "{}"))
  1412. X                continue;
  1413. X        while (c = *p++)
  1414. X            (*f)(c);
  1415. X    }
  1416. X}
  1417. X/*
  1418. static
  1419. scan(t, f)
  1420. X    register char **t;
  1421. X    int (*f)();
  1422. X{
  1423. X    register char *p, c;
  1424. X
  1425. X    while (p = *t++)
  1426. X        while (c = *p)
  1427. X            *p++ = (*f)(c);
  1428. X} */
  1429. X
  1430. static
  1431. tglob(c)
  1432. X    register char c;
  1433. X{
  1434. X
  1435. X    if (any(c, globchars))
  1436. X        gflag |= c == '{' ? 2 : 1;
  1437. X    return (c);
  1438. X}
  1439. X/*
  1440. static
  1441. trim(c)
  1442. X    char c;
  1443. X{
  1444. X
  1445. X    return (c & TRIM);
  1446. X} */
  1447. X
  1448. X
  1449. letter(c)
  1450. X    register char c;
  1451. X{
  1452. X
  1453. X    return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
  1454. X}
  1455. X
  1456. digit(c)
  1457. X    register char c;
  1458. X{
  1459. X
  1460. X    return (c >= '0' && c <= '9');
  1461. X}
  1462. X
  1463. any(c, s)
  1464. X    register int c;
  1465. X    register char *s;
  1466. X{
  1467. X
  1468. X    while (*s)
  1469. X        if (*s++ == c)
  1470. X            return(1);
  1471. X    return(0);
  1472. X}
  1473. blklen(av)
  1474. X    register char **av;
  1475. X{
  1476. X    register int i = 0;
  1477. X
  1478. X    while (*av++)
  1479. X        i++;
  1480. X    return (i);
  1481. X}
  1482. X
  1483. char **
  1484. blkcpy(oav, bv)
  1485. X    char **oav;
  1486. X    register char **bv;
  1487. X{
  1488. X    register char **av = oav;
  1489. X
  1490. X    while (*av++ = *bv++)
  1491. X        continue;
  1492. X    return (oav);
  1493. X}
  1494. X
  1495. blkfree(av0)
  1496. X    char **av0;
  1497. X{
  1498. X    register char **av = av0;
  1499. X
  1500. X    while (*av)
  1501. X        free(*av++);
  1502. X    free((char *)av0);
  1503. X}
  1504. X
  1505. static
  1506. char *
  1507. strspl(cp, dp)
  1508. X    register char *cp, *dp;
  1509. X{
  1510. X    register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  1511. X
  1512. X    if (ep == (char *)0)
  1513. X        fatal("Out of memory");
  1514. X    (void) strcpy(ep, cp);
  1515. X    (void) strcat(ep, dp);
  1516. X    return (ep);
  1517. X}
  1518. X
  1519. char **
  1520. copyblk(v)
  1521. X    register char **v;
  1522. X{
  1523. X    register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
  1524. X                        sizeof(char **)));
  1525. X    if (nv == (char **)0)
  1526. X        fatal("Out of memory");
  1527. X
  1528. X    return (blkcpy(nv, v));
  1529. X}
  1530. X
  1531. static
  1532. char *
  1533. strend(cp)
  1534. X    register char *cp;
  1535. X{
  1536. X
  1537. X    while (*cp)
  1538. X        cp++;
  1539. X    return (cp);
  1540. X}
  1541. X/*
  1542. X * Extract a home directory from the password file
  1543. X * The argument points to a buffer where the name of the
  1544. X * user whose home directory is sought is currently.
  1545. X * We write the home directory of the user back there.
  1546. X */
  1547. gethdir(home)
  1548. X    char *home;
  1549. X{
  1550. X    register struct passwd *pp = getpwnam(home);
  1551. X
  1552. X    if (pp == 0)
  1553. X        return (1);
  1554. X    (void) strcpy(home, pp->pw_dir);
  1555. X    return (0);
  1556. X}
  1557. END_OF_FILE
  1558. if test 9587 -ne `wc -c <'in.ftpd/glob.c'`; then
  1559.     echo shar: \"'in.ftpd/glob.c'\" unpacked with wrong size!
  1560. fi
  1561. # end of 'in.ftpd/glob.c'
  1562. fi
  1563. if test -f 'login/login.c' -a "${1}" != "-c" ; then 
  1564.   echo shar: Will not clobber existing file \"'login/login.c'\"
  1565. else
  1566. echo shar: Extracting \"'login/login.c'\" \(15072 characters\)
  1567. sed "s/^X//" >'login/login.c' <<'END_OF_FILE'
  1568. X/*
  1569. X * Copyright (c) 1980 Regents of the University of California.
  1570. X * All rights reserved.  The Berkeley software License Agreement
  1571. X * specifies the terms and conditions for redistribution.
  1572. X */
  1573. X
  1574. X#ifndef lint
  1575. char copyright[] =
  1576. X"@(#) Copyright (c) 1980 Regents of the University of California.\n\
  1577. X All rights reserved.\n";
  1578. X#endif not lint
  1579. X
  1580. X#ifndef lint
  1581. static char sccsid[] = "@(#)login.c    5.15 (Berkeley) 4/12/86";
  1582. X#endif not lint
  1583. X
  1584. X/*
  1585. X * login [ name ]
  1586. X * login -r hostname (for rlogind)
  1587. X * login -h hostname (for telnetd, etc.)
  1588. X */
  1589. X
  1590. X#include <sys/param.h>
  1591. X#include <sys/stat.h>
  1592. X#include <sys/time.h>
  1593. X#include <sys/resource.h>
  1594. X#include <sys/file.h>
  1595. X
  1596. X#include <sgtty.h>
  1597. X#include <utmp.h>
  1598. X#include <signal.h>
  1599. X#include <pwd.h>
  1600. X#include <stdio.h>
  1601. X#include <lastlog.h>
  1602. X#include <errno.h>
  1603. X#include <ttyent.h>
  1604. X#include <syslog.h>
  1605. X#include <grp.h>
  1606. X
  1607. X#ifdef MAILPING
  1608. X#include <sys/socket.h>
  1609. X#include <netinet/in.h>
  1610. X#include <netdb.h>
  1611. char mailhost[] = "mailhost";
  1612. X#endif
  1613. X
  1614. X#ifdef PERMS
  1615. char *strdup(), *grpnames[NGROUPS+1];
  1616. int ngrps, lp;
  1617. struct group *grp;
  1618. extern int permcheck();
  1619. X#endif
  1620. X
  1621. X#define TTYGRPNAME    "tty"        /* name of group to own ttys */
  1622. X#define TTYGID(gid)    tty_gid(gid)    /* gid that owns all ttys */
  1623. X
  1624. X#define    SCMPN(a, b)    strncmp(a, b, sizeof(a))
  1625. X#define    SCPYN(a, b)    strncpy(a, b, sizeof(a))
  1626. X
  1627. X#define NMAX    sizeof(utmp.ut_name)
  1628. X#define HMAX    sizeof(utmp.ut_host)
  1629. X
  1630. X#define    FALSE    0
  1631. X#define    TRUE    -1
  1632. X
  1633. X#define QUOTAWARN       "/usr/ucb/quota -q"        /* warn user about quotas */
  1634. X
  1635. char    nolog[] =    "/etc/nologin";
  1636. char    qlog[]  =    ".hushlogin";
  1637. char    maildir[30] =    "/usr/spool/mail/";
  1638. char    lastlog[] =    "/usr/adm/lastlog";
  1639. struct    passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" };
  1640. struct    sgttyb ttyb;
  1641. struct    utmp utmp;
  1642. char    minusnam[16] = "-";
  1643. char    *envinit[] = { 0 };        /* now set by setenv calls */
  1644. X/*
  1645. X * This bounds the time given to login.  We initialize it here
  1646. X * so it can be patched on machines where it's too small.
  1647. X */
  1648. int    timeout = 60;
  1649. X
  1650. char    term[64];
  1651. X
  1652. struct    passwd *pwd;
  1653. char    *strcat(), *rindex(), *index(), *malloc(), *realloc();
  1654. int    timedout();
  1655. char    *ttyname();
  1656. char    *crypt();
  1657. char    *getpass();
  1658. char    *stypeof();
  1659. extern    char **environ;
  1660. extern    int errno;
  1661. X
  1662. struct    tchars tc = {
  1663. X    CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
  1664. X};
  1665. struct    ltchars ltc = {
  1666. X    CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
  1667. X};
  1668. X
  1669. struct winsize win = { 0, 0, 0, 0 };
  1670. X
  1671. int    rflag;
  1672. int    usererr = -1;
  1673. char    rusername[NMAX+1], lusername[NMAX+1];
  1674. char    rpassword[NMAX+1];
  1675. char    name[NMAX+1];
  1676. char    *rhost;
  1677. X
  1678. main(argc, argv)
  1679. X    char *argv[];
  1680. X{
  1681. X    register char *namep;
  1682. X    int pflag = 0, hflag = 0, t, f, c;
  1683. X    int invalid, quietlog;
  1684. X    FILE *nlfd;
  1685. X    char *ttyn, *tty;
  1686. X    int ldisc = 0, zero = 0, i;
  1687. X    char **envnew;
  1688. X
  1689. X    signal(SIGALRM, timedout);
  1690. X    alarm(timeout);
  1691. X    signal(SIGQUIT, SIG_IGN);
  1692. X    signal(SIGINT, SIG_IGN);
  1693. X    setpriority(PRIO_PROCESS, 0, 0);
  1694. X    /*
  1695. X     * -p is used by getty to tell login not to destroy the environment
  1696. X     * -r is used by rlogind to cause the autologin protocol;
  1697. X     * -h is used by other servers to pass the name of the
  1698. X     * remote host to login so that it may be placed in utmp and wtmp
  1699. X     */
  1700. X    while (argc > 1) {
  1701. X        if (strcmp(argv[1], "-r") == 0) {
  1702. X            if (rflag || hflag) {
  1703. X                printf("Only one of -r and -h allowed\n");
  1704. X                exit(1);
  1705. X            }
  1706. X            rflag = 1;
  1707. X            usererr = doremotelogin(argv[2]);
  1708. X            SCPYN(utmp.ut_host, argv[2]);
  1709. X            argc -= 2;
  1710. X            argv += 2;
  1711. X            continue;
  1712. X        }
  1713. X        if (strcmp(argv[1], "-h") == 0 && getuid() == 0) {
  1714. X            if (rflag || hflag) {
  1715. X                printf("Only one of -r and -h allowed\n");
  1716. X                exit(1);
  1717. X            }
  1718. X            hflag = 1;
  1719. X            SCPYN(utmp.ut_host, argv[2]);
  1720. X            argc -= 2;
  1721. X            argv += 2;
  1722. X            continue;
  1723. X        }
  1724. X        if (strcmp(argv[1], "-p") == 0) {
  1725. X            argc--;
  1726. X            argv++;
  1727. X            pflag = 1;
  1728. X            continue;
  1729. X        }
  1730. X        break;
  1731. X    }
  1732. X    ioctl(0, TIOCLSET, &zero);
  1733. X    ioctl(0, TIOCNXCL, 0);
  1734. X    ioctl(0, FIONBIO, &zero);
  1735. X    ioctl(0, FIOASYNC, &zero);
  1736. X    ioctl(0, TIOCGETP, &ttyb);
  1737. X    /*
  1738. X     * If talking to an rlogin process,
  1739. X     * propagate the terminal type and
  1740. X     * baud rate across the network.
  1741. X     */
  1742. X    if (rflag)
  1743. X        doremoteterm(term, &ttyb);
  1744. X    ttyb.sg_erase = CERASE;
  1745. X    ttyb.sg_kill = CKILL;
  1746. X    ioctl(0, TIOCSLTC, <c);
  1747. X    ioctl(0, TIOCSETC, &tc);
  1748. X    ioctl(0, TIOCSETP, &ttyb);
  1749. X    for (t = getdtablesize(); t > 2; t--)
  1750. X        close(t);
  1751. X    ttyn = ttyname(0);
  1752. X    if (ttyn == (char *)0 || *ttyn == '\0')
  1753. X        ttyn = "/dev/tty??";
  1754. X    tty = rindex(ttyn, '/');
  1755. X    if (tty == NULL)
  1756. X        tty = ttyn;
  1757. X    else
  1758. X        tty++;
  1759. X    openlog("login", LOG_ODELAY, LOG_AUTH);
  1760. X    t = 0;
  1761. X    invalid = FALSE;
  1762. X    do {
  1763. X        ldisc = 0;
  1764. X        ioctl(0, TIOCSETD, &ldisc);
  1765. X        SCPYN(utmp.ut_name, "");
  1766. X        /*
  1767. X         * Name specified, take it.
  1768. X         */
  1769. X        if (argc > 1) {
  1770. X            SCPYN(utmp.ut_name, argv[1]);
  1771. X            argc = 0;
  1772. X        }
  1773. X        /*
  1774. X         * If remote login take given name,
  1775. X         * otherwise prompt user for something.
  1776. X         */
  1777. X        if (rflag && !invalid)
  1778. X            SCPYN(utmp.ut_name, lusername);
  1779. X        else
  1780. X            getloginname(&utmp);
  1781. X        invalid = FALSE;
  1782. X        if (!strcmp(pwd->pw_shell, "/bin/csh")) {
  1783. X            ldisc = NTTYDISC;
  1784. X            ioctl(0, TIOCSETD, &ldisc);
  1785. X        }
  1786. X        /*
  1787. X         * If no remote login authentication and
  1788. X         * a password exists for this user, prompt
  1789. X         * for one and verify it.
  1790. X         */
  1791. X        if (usererr == -1 && *pwd->pw_passwd != '\0') {
  1792. X            char *pp;
  1793. X
  1794. X            setpriority(PRIO_PROCESS, 0, -4);
  1795. X            pp = getpass("Password:");
  1796. X            namep = crypt(pp, pwd->pw_passwd);
  1797. X            setpriority(PRIO_PROCESS, 0, 0);
  1798. X            if (strcmp(namep, pwd->pw_passwd))
  1799. X                invalid = TRUE;
  1800. X        }
  1801. X        /*
  1802. X         * If user not super-user, check for logins disabled.
  1803. X         */
  1804. X        if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) {
  1805. X            while ((c = getc(nlfd)) != EOF)
  1806. X                putchar(c);
  1807. X            fflush(stdout);
  1808. X            sleep(5);
  1809. X            exit(0);
  1810. X        }
  1811. X        /*
  1812. X         * If valid so far and root is logging in,
  1813. X         * see if root logins on this terminal are permitted.
  1814. X         */
  1815. X        if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) {
  1816. X            if (utmp.ut_host[0])
  1817. X                syslog(LOG_CRIT,
  1818. X                    "ROOT LOGIN REFUSED ON %s FROM %.*s",
  1819. X                    tty, HMAX, utmp.ut_host);
  1820. X            else
  1821. X                syslog(LOG_CRIT,
  1822. X                    "ROOT LOGIN REFUSED ON %s", tty);
  1823. X            invalid = TRUE;
  1824. X        }
  1825. X#ifdef PERMS
  1826. X        /* build groups so we can look them up in 'permissions'
  1827. X         * this check is not run for uid 0
  1828. X         */
  1829. X        if(!invalid && pwd->pw_uid != 0) {
  1830. X            setgrent();
  1831. X            ngrps = 0;
  1832. X            if(!(grp=getgrgid(pwd->pw_gid))) {
  1833. X                syslog(LOG_CRIT,
  1834. X                    "cannot find group name for %d\n", pwd->pw_gid);
  1835. X                goto broken_groups;
  1836. X            }
  1837. X            grpnames[ngrps++] = strdup(grp->gr_name);
  1838. X            while( grp=getgrent() ) {
  1839. X                if(pwd->pw_gid == grp->gr_gid)
  1840. X                    continue;
  1841. X                while(*grp->gr_mem) {
  1842. X                    if( !strcmp(lusername, *grp->gr_mem)) {
  1843. X                        grpnames[ngrps++] = strdup(grp->gr_name);
  1844. X                    }
  1845. X                    grp->gr_mem++;
  1846. X                }
  1847. X            }
  1848. X            endgrent();
  1849. X            grpnames[ngrps] = NULL;
  1850. X            lp = permcheck(lusername, tty, grpnames, NULL);
  1851. X            if(!lp) {
  1852. X                syslog(LOG_CRIT,
  1853. X                    "%s:%s not permitted", tty, lusername);
  1854. X                printf("Permission denied.\n");
  1855. X                exit(1);
  1856. X            }
  1857. X        }
  1858. broken_groups:
  1859. X#endif
  1860. X        if (invalid) {
  1861. X            printf("Login incorrect\n");
  1862. X            if (++t >= 5) {
  1863. X                if (utmp.ut_host[0])
  1864. X                    syslog(LOG_CRIT,
  1865. X                        "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s",
  1866. X                        tty, HMAX, utmp.ut_host,
  1867. X                        NMAX, utmp.ut_name);
  1868. X                else
  1869. X                    syslog(LOG_CRIT,
  1870. X                        "REPEATED LOGIN FAILURES ON %s, %.*s",
  1871. X                        tty, NMAX, utmp.ut_name);
  1872. X                ioctl(0, TIOCHPCL, (struct sgttyb *) 0);
  1873. X                close(0), close(1), close(2);
  1874. X                sleep(10);
  1875. X                exit(1);
  1876. X            }
  1877. X        }
  1878. X        if (*pwd->pw_shell == '\0')
  1879. X            pwd->pw_shell = "/bin/sh";
  1880. X        if (chdir(pwd->pw_dir) < 0 && !invalid ) {
  1881. X            if (chdir("/") < 0) {
  1882. X                printf("No directory!\n");
  1883. X                invalid = TRUE;
  1884. X            } else {
  1885. X                printf("No directory! %s\n",
  1886. X                   "Logging in with home=/");
  1887. X                pwd->pw_dir = "/";
  1888. X            }
  1889. X        }
  1890. X        /*
  1891. X         * Remote login invalid must have been because
  1892. X         * of a restriction of some sort, no extra chances.
  1893. X         */
  1894. X        if (!usererr && invalid)
  1895. X            exit(1);
  1896. X    } while (invalid);
  1897. X/* committed to login turn off timeout */
  1898. X    alarm(0);
  1899. X
  1900. X    time(&utmp.ut_time);
  1901. X    t = ttyslot();
  1902. X    if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) {
  1903. X        lseek(f, (long)(t*sizeof(utmp)), 0);
  1904. X        SCPYN(utmp.ut_line, tty);
  1905. X        write(f, (char *)&utmp, sizeof(utmp));
  1906. X        close(f);
  1907. X    }
  1908. X    if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) {
  1909. X        write(f, (char *)&utmp, sizeof(utmp));
  1910. X        close(f);
  1911. X    }
  1912. X    quietlog = access(qlog, F_OK) == 0;
  1913. X    if ((f = open(lastlog, O_RDWR)) >= 0) {
  1914. X        struct lastlog ll;
  1915. X
  1916. X        lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
  1917. X        if (read(f, (char *) &ll, sizeof ll) == sizeof ll &&
  1918. X            ll.ll_time != 0 && !quietlog) {
  1919. X            printf("Last login: %.*s ",
  1920. X                24-5, (char *)ctime(&ll.ll_time));
  1921. X            if (*ll.ll_host != '\0')
  1922. X                printf("from %.*s\n",
  1923. X                    sizeof (ll.ll_host), ll.ll_host);
  1924. X            else
  1925. X                printf("on %.*s\n",
  1926. X                    sizeof (ll.ll_line), ll.ll_line);
  1927. X        }
  1928. X        lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
  1929. X        time(&ll.ll_time);
  1930. X        SCPYN(ll.ll_line, tty);
  1931. X        SCPYN(ll.ll_host, utmp.ut_host);
  1932. X        write(f, (char *) &ll, sizeof ll);
  1933. X        close(f);
  1934. X    }
  1935. X    chown(ttyn, pwd->pw_uid, TTYGID(pwd->pw_gid));
  1936. X    if (!hflag && !rflag)                    /* XXX */
  1937. X        ioctl(0, TIOCSWINSZ, &win);
  1938. X    chmod(ttyn, 0620);
  1939. X    setgid(pwd->pw_gid);
  1940. X    strncpy(name, utmp.ut_name, NMAX);
  1941. X    name[NMAX] = '\0';
  1942. X    initgroups(name, pwd->pw_gid);
  1943. X    setuid(pwd->pw_uid);
  1944. X    /* destroy environment unless user has asked to preserve it */
  1945. X    if (!pflag)
  1946. X        environ = envinit;
  1947. X
  1948. X    /* set up environment, this time without destruction */
  1949. X    /* copy the environment before setenving */
  1950. X    i = 0;
  1951. X    while (environ[i] != NULL)
  1952. X        i++;
  1953. X    envnew = (char **) malloc(sizeof (char *) * (i + 1));
  1954. X    for (; i >= 0; i--)
  1955. X        envnew[i] = environ[i];
  1956. X    environ = envnew;
  1957. X
  1958. X    setenv("HOME=", pwd->pw_dir, 1);
  1959. X    setenv("SHELL=", pwd->pw_shell, 1);
  1960. X    if (term[0] == '\0')
  1961. X        strncpy(term, stypeof(tty), sizeof(term));
  1962. X    setenv("TERM=", term, 0);
  1963. X    setenv("USER=", pwd->pw_name, 1);
  1964. X    setenv("PATH=", ":/usr/ucb:/bin:/usr/bin", 0);
  1965. X
  1966. X    if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
  1967. X        namep = pwd->pw_shell;
  1968. X    else
  1969. X        namep++;
  1970. X    strcat(minusnam, namep);
  1971. X    if (tty[sizeof("tty")-1] == 'd')
  1972. X        syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
  1973. X    if (pwd->pw_uid == 0)
  1974. X        if (utmp.ut_host[0])
  1975. X            syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
  1976. X                tty, HMAX, utmp.ut_host);
  1977. X        else
  1978. X            syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
  1979. X    if (!quietlog) {
  1980. X        struct stat st;
  1981. X
  1982. X        showmotd();
  1983. X        strcat(maildir, pwd->pw_name);
  1984. X#ifdef MAILPING
  1985. X        if(!serverup())
  1986. X            printf("No idea if you have mail.\n");
  1987. X        else
  1988. X#endif
  1989. X        if (stat(maildir, &st) == 0 && st.st_size != 0)
  1990. X            printf("You have %smail.\n",
  1991. X                (st.st_mtime > st.st_atime) ? "new " : "");
  1992. X        system(QUOTAWARN);
  1993. X    }
  1994. X    signal(SIGALRM, SIG_DFL);
  1995. X    signal(SIGQUIT, SIG_DFL);
  1996. X    signal(SIGINT, SIG_DFL);
  1997. X    signal(SIGTSTP, SIG_IGN);
  1998. X    execlp(pwd->pw_shell, minusnam, 0);
  1999. X    perror(pwd->pw_shell);
  2000. X    printf("No shell\n");
  2001. X    exit(0);
  2002. X}
  2003. X
  2004. getloginname(up)
  2005. X    register struct utmp *up;
  2006. X{
  2007. X    register char *namep;
  2008. X    char c;
  2009. X
  2010. X    while (up->ut_name[0] == '\0') {
  2011. X        namep = up->ut_name;
  2012. X        printf("login: ");
  2013. X        while ((c = getchar()) != '\n') {
  2014. X            if (c == ' ')
  2015. X                c = '_';
  2016. X            if (c == EOF)
  2017. X                exit(0);
  2018. X            if (namep < up->ut_name+NMAX)
  2019. X                *namep++ = c;
  2020. X        }
  2021. X    }
  2022. X    strncpy(lusername, up->ut_name, NMAX);
  2023. X    lusername[NMAX] = 0;
  2024. X    if ((pwd = getpwnam(lusername)) == NULL)
  2025. X        pwd = &nouser;
  2026. X}
  2027. X
  2028. timedout()
  2029. X{
  2030. X
  2031. X    printf("Login timed out after %d seconds\n", timeout);
  2032. X    exit(0);
  2033. X}
  2034. X
  2035. int    stopmotd;
  2036. catch()
  2037. X{
  2038. X
  2039. X    signal(SIGINT, SIG_IGN);
  2040. X    stopmotd++;
  2041. X}
  2042. X
  2043. rootterm(tty)
  2044. X    char *tty;
  2045. X{
  2046. X    register struct ttyent *t;
  2047. X
  2048. X    if ((t = getttynam(tty)) != NULL) {
  2049. X        if (t->ty_status & TTY_SECURE)
  2050. X            return (1);
  2051. X    }
  2052. X    return (0);
  2053. X}
  2054. X
  2055. showmotd()
  2056. X{
  2057. X    FILE *mf;
  2058. X    register c;
  2059. X
  2060. X    signal(SIGINT, catch);
  2061. X    if ((mf = fopen("/etc/motd", "r")) != NULL) {
  2062. X        while ((c = getc(mf)) != EOF && stopmotd == 0)
  2063. X            putchar(c);
  2064. X        fclose(mf);
  2065. X    }
  2066. X    signal(SIGINT, SIG_IGN);
  2067. X}
  2068. X
  2069. X#undef    UNKNOWN
  2070. X#define UNKNOWN "su"
  2071. X
  2072. char *
  2073. stypeof(ttyid)
  2074. X    char *ttyid;
  2075. X{
  2076. X    register struct ttyent *t;
  2077. X
  2078. X    if (ttyid == NULL || (t = getttynam(ttyid)) == NULL)
  2079. X        return (UNKNOWN);
  2080. X    return (t->ty_type);
  2081. X}
  2082. X
  2083. doremotelogin(host)
  2084. X    char *host;
  2085. X{
  2086. X    getstr(rusername, sizeof (rusername), "remuser");
  2087. X    getstr(lusername, sizeof (lusername), "locuser");
  2088. X    getstr(term, sizeof(term), "Terminal type");
  2089. X    if (getuid()) {
  2090. X        pwd = &nouser;
  2091. X        return(-1);
  2092. X    }
  2093. X    pwd = getpwnam(lusername);
  2094. X    if (pwd == NULL) {
  2095. X        pwd = &nouser;
  2096. X        return(-1);
  2097. X    }
  2098. X    return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername));
  2099. X}
  2100. X
  2101. getstr(buf, cnt, err)
  2102. X    char *buf;
  2103. X    int cnt;
  2104. X    char *err;
  2105. X{
  2106. X    char c;
  2107. X
  2108. X    do {
  2109. X        if (read(0, &c, 1) != 1)
  2110. X            exit(1);
  2111. X        if (--cnt < 0) {
  2112. X            printf("%s too long\r\n", err);
  2113. X            exit(1);
  2114. X        }
  2115. X        *buf++ = c;
  2116. X    } while (c != 0);
  2117. X}
  2118. X
  2119. char    *speeds[] =
  2120. X    { "0", "50", "75", "110", "134", "150", "200", "300",
  2121. X      "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
  2122. X#define    NSPEEDS    (sizeof (speeds) / sizeof (speeds[0]))
  2123. X
  2124. doremoteterm(term, tp)
  2125. X    char *term;
  2126. X    struct sgttyb *tp;
  2127. X{
  2128. X    register char *cp = index(term, '/'), **cpp;
  2129. X    char *speed;
  2130. X
  2131. X    if (cp) {
  2132. X        *cp++ = '\0';
  2133. X        speed = cp;
  2134. X        cp = index(speed, '/');
  2135. X        if (cp)
  2136. X            *cp++ = '\0';
  2137. X        for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
  2138. X            if (strcmp(*cpp, speed) == 0) {
  2139. X                tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
  2140. X                break;
  2141. X            }
  2142. X    }
  2143. X    tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
  2144. X}
  2145. X
  2146. X/*
  2147. X * Set the value of var to be arg in the Unix 4.2 BSD environment env.
  2148. X * Var should end with '='.
  2149. X * (bindings are of the form "var=value")
  2150. X * This procedure assumes the memory for the first level of environ
  2151. X * was allocated using malloc.
  2152. X */
  2153. setenv(var, value, clobber)
  2154. X    char *var, *value;
  2155. X{
  2156. X    extern char **environ;
  2157. X    int index = 0;
  2158. X    int varlen = strlen(var);
  2159. X    int vallen = strlen(value);
  2160. X
  2161. X    for (index = 0; environ[index] != NULL; index++) {
  2162. X        if (strncmp(environ[index], var, varlen) == 0) {
  2163. X            /* found it */
  2164. X            if (!clobber)
  2165. X                return;
  2166. X            environ[index] = malloc(varlen + vallen + 1);
  2167. X            strcpy(environ[index], var);
  2168. X            strcat(environ[index], value);
  2169. X            return;
  2170. X        }
  2171. X    }
  2172. X    environ = (char **) realloc(environ, sizeof (char *) * (index + 2));
  2173. X    if (environ == NULL) {
  2174. X        fprintf(stderr, "login: malloc out of memory\n");
  2175. X        exit(1);
  2176. X    }
  2177. X    environ[index] = malloc(varlen + vallen + 1);
  2178. X    strcpy(environ[index], var);
  2179. X    strcat(environ[index], value);
  2180. X    environ[++index] = NULL;
  2181. X}
  2182. X
  2183. tty_gid(default_gid)
  2184. X    int default_gid;
  2185. X{
  2186. X    struct group *getgrnam(), *gr;
  2187. X    int gid = default_gid;
  2188. X
  2189. X    gr = getgrnam(TTYGRPNAME);
  2190. X    if (gr != (struct group *) 0)
  2191. X        gid = gr->gr_gid;
  2192. X
  2193. X    endgrent();
  2194. X
  2195. X    return (gid);
  2196. X}
  2197. X
  2198. X#ifdef MAILPING
  2199. X/* ping mailhost, at port echo/udp
  2200. X * determine if server is up=1
  2201. X * if unable, default to down=0
  2202. X */
  2203. serverup()
  2204. X{
  2205. X    struct sockaddr_in sin;
  2206. X    struct hostent *hent;
  2207. X    struct servent *sent;
  2208. X    struct timeval tv;
  2209. X    int s, count, tsize;
  2210. X    fd_set fdin;
  2211. X
  2212. X    if( !(hent=gethostbyname(mailhost)))
  2213. X        return 0;
  2214. X    if( !(sent=getservbyname("echo", "udp")))
  2215. X        return 0;
  2216. X
  2217. X    bzero(&sin, sizeof sin);
  2218. X    sin.sin_family = hent->h_addrtype;
  2219. X    bcopy((char *)hent->h_addr, (char *)&sin.sin_addr, hent->h_length);
  2220. X    sin.sin_port = sent->s_port;
  2221. X
  2222. X    if( (s=socket(AF_INET, SOCK_DGRAM, 0)) <0)
  2223. X        return 0;
  2224. X
  2225. X    tsize = getdtablesize();
  2226. X    tv.tv_sec = 1;
  2227. X    tv.tv_usec = 0;
  2228. X    for(count=0; count<10; count++) {
  2229. X        FD_ZERO(&fdin);
  2230. X        FD_SET(s, &fdin);
  2231. X        switch( select(tsize, &fdin, NULL, NULL, &tv) ) {
  2232. X        case -1:
  2233. X            perror("select");
  2234. X            break;
  2235. X        case 0:
  2236. X            if( sendto(s, "UP?", 3, 0, &sin, sizeof sin) < 0)
  2237. X                perror("sendto");
  2238. X            break;
  2239. X        case 1:
  2240. X            close(s);
  2241. X            return 1;
  2242. X        }
  2243. X    }
  2244. X
  2245. X    close(s);
  2246. X    return 0;
  2247. X}
  2248. X#endif
  2249. END_OF_FILE
  2250. if test 15072 -ne `wc -c <'login/login.c'`; then
  2251.     echo shar: \"'login/login.c'\" unpacked with wrong size!
  2252. fi
  2253. # end of 'login/login.c'
  2254. fi
  2255. echo shar: End of archive 2 \(of 3\).
  2256. cp /dev/null ark2isdone
  2257. MISSING=""
  2258. for I in 1 2 3 ; do
  2259.     if test ! -f ark${I}isdone ; then
  2260.     MISSING="${MISSING} ${I}"
  2261.     fi
  2262. done
  2263. if test "${MISSING}" = "" ; then
  2264.     echo You have unpacked all 3 archives.
  2265.     rm -f ark[1-9]isdone
  2266. else
  2267.     echo You still need to unpack the following archives:
  2268.     echo "        " ${MISSING}
  2269. fi
  2270. ##  End of shell archive.
  2271. exit 0
  2272.  
  2273.