| 1 | /* Copyright (c) 1979 Regents of the University of California */ |
| 2 | # include <sgtty.h> |
| 3 | # include <stdio.h> |
| 4 | |
| 5 | /* |
| 6 | ** TSET -- set terminal modes |
| 7 | ** |
| 8 | ** This program does sophisticated terminal initialization. |
| 9 | ** I recommend that you include it in your .start_up or .login |
| 10 | ** file to initialize whatever terminal you are on. |
| 11 | ** |
| 12 | ** There are several features: |
| 13 | ** |
| 14 | ** A special file or sequence (as controlled by the ttycap file) |
| 15 | ** is sent to the terminal. |
| 16 | ** |
| 17 | ** Mode bits are set on a per-terminal_type basis (much better |
| 18 | ** than UNIX itself). This allows special delays, automatic |
| 19 | ** tabs, etc. |
| 20 | ** |
| 21 | ** Erase and Kill characters can be set to whatever you want. |
| 22 | ** Default is to change erase to control-H on a terminal which |
| 23 | ** can overstrike, and leave it alone on anything else. Kill |
| 24 | ** is always left alone unless specifically requested. |
| 25 | ** |
| 26 | ** Terminals which are dialups or plugboard types can be aliased |
| 27 | ** to whatever type you may have in your home or office. Thus, |
| 28 | ** if you know that when you dial up you will always be on a |
| 29 | ** TI 733, you can specify that fact to tset. |
| 30 | ** |
| 31 | ** The htmp file, used by ex, etc., can be updated. |
| 32 | ** |
| 33 | ** The current terminal type can be queried. |
| 34 | ** |
| 35 | ** Usage: |
| 36 | ** tset [-] [-r] [-EC] [-eC] [-d type] [-p type] |
| 37 | ** [-b type] [-h] [-u] [type] |
| 38 | ** |
| 39 | ** In systems with environments, use: |
| 40 | ** setenv TERM `tset - ...` |
| 41 | ** |
| 42 | ** Positional Parameters: |
| 43 | ** type -- the terminal type to force. If this is |
| 44 | ** specified, initialization is for this |
| 45 | ** terminal type. |
| 46 | ** |
| 47 | ** Flags: |
| 48 | ** - -- report terminal type. Whatever type is |
| 49 | ** decided on is reported. |
| 50 | ** -r -- report to user, on diagnostic output instead |
| 51 | ** of standard output. |
| 52 | ** -EC -- set the erase character to C on all terminals |
| 53 | ** except those which cannot backspace (e.g., |
| 54 | ** a TTY 33). C defaults to control-H. |
| 55 | ** -eC -- set the erase character to C on all terminals. |
| 56 | ** C defaults to control-H. If neither -E or -e |
| 57 | ** are specified, the erase character is set to |
| 58 | ** control-H if the terminal can both backspace |
| 59 | ** and not overstrike (e.g., a CRT). If the erase |
| 60 | ** character is NULL (zero byte), it will be reset |
| 61 | ** to '#' if nothing else is specified. |
| 62 | ** -kC -- set the kill character to C on all terminals. |
| 63 | ** Default for C is control-X. If not specified, |
| 64 | ** the kill character is untouched; however, if |
| 65 | ** not specified and the kill character is NULL |
| 66 | ** (zero byte), the kill character is set to '@'. |
| 67 | ** -d type -- set the dialup type to be type. If the |
| 68 | ** terminal type seems to be dialup, make it |
| 69 | ** 'type' instead. There need not be a space |
| 70 | ** between 'd' and 'type'. |
| 71 | ** -p type -- ditto for a plugboard. |
| 72 | ** -b type -- ditto for a bussiplexer. |
| 73 | ** -h -- don't read htmp file. Normally the terminal type |
| 74 | ** is determined by reading the htmp file (unless |
| 75 | ** -d or -p are specified). This forces a read |
| 76 | ** of the ttytype file -- useful when htmp is |
| 77 | ** somehow wrong. On a version seven system, this |
| 78 | ** flag means don't look at the TERM entry in |
| 79 | ** the environment. |
| 80 | ** -u -- don't update htmp. It seemed like this should |
| 81 | ** be put in. Note that htmp is never actually |
| 82 | ** written if there are no changes, so don't bother |
| 83 | ** bother using this for efficiency reasons alone. |
| 84 | ** On version seven systems this flag is ignored. |
| 85 | ** |
| 86 | ** Files: |
| 87 | ** /etc/ttytype |
| 88 | ** contains a terminal id -> terminal type |
| 89 | ** mapping; used when -h, -d, or -p is used. |
| 90 | ** /etc/termcap |
| 91 | ** a terminal_type -> terminal_capabilities |
| 92 | ** mapping. |
| 93 | ** |
| 94 | ** Return Codes: |
| 95 | ** -1 -- couldn't open ttycap. |
| 96 | ** 1 -- bad terminal type, or standard output not tty. |
| 97 | ** 0 -- ok. |
| 98 | ** |
| 99 | ** Defined Constants: |
| 100 | ** DIALUP -- the type code for a dialup port |
| 101 | ** PLUGBOARD -- the code for a plugboard port. |
| 102 | ** BUSSIPLEXER -- the code for a bussiplexer port. |
| 103 | ** BACKSPACE -- control-H, the default for -e. |
| 104 | ** CONTROLX -- control-X, the default for -k. |
| 105 | ** OLDERASE -- the system default erase character. |
| 106 | ** OLDKILL -- the system default kill character. |
| 107 | ** FILEDES -- the file descriptor to do the operation |
| 108 | ** on, nominally 1 or 2. |
| 109 | ** STDOUT -- the standard output file descriptor. |
| 110 | ** UIDMASK -- the bit pattern to mask with the getuid() |
| 111 | ** call to get just the user id. |
| 112 | ** |
| 113 | ** Requires: |
| 114 | ** Routines to handle htmp, ttytype, and ttycap. |
| 115 | ** |
| 116 | ** Compilation Flags: |
| 117 | ** PLUGBOARD -- if defined, accept the -p flag. |
| 118 | ** BUSSIPLEXER -- if defined, accept the -b flag. |
| 119 | ** FULLLOGIN -- if defined, login sets the ttytype from |
| 120 | ** /etc/ttytype file. |
| 121 | ** VERSION7 -- if set, use environments, not htmp. |
| 122 | ** Also, use 'ioctl' not 'stty' -- to get type- |
| 123 | ** ahead. |
| 124 | ** GTTYN -- if set, uses generalized tty names. |
| 125 | ** |
| 126 | ** Compilation Instructions: |
| 127 | ** cc -n -O tset.c -lX |
| 128 | ** mv a.out tset |
| 129 | ** chown bin tset |
| 130 | ** chmod 4755 tset |
| 131 | ** |
| 132 | ** where 'bin' should be whoever owns the 'htmp' file. |
| 133 | ** If 'htmp' is 666, then tset need not be setuid. |
| 134 | ** |
| 135 | ** Author: |
| 136 | ** Eric Allman |
| 137 | ** Electronics Research Labs |
| 138 | ** U.C. Berkeley |
| 139 | ** |
| 140 | ** History: |
| 141 | ** 3/79 -- Use ioctl in version7. |
| 142 | ** 12/78 -- modified for eventual migration to VAX/UNIX, |
| 143 | ** so the '-' option is changed to output only |
| 144 | ** the terminal type to STDOUT instead of |
| 145 | ** FILEDES. FULLLOGIN flag added. BUSSIPLEXER |
| 146 | ** and -r added. |
| 147 | ** 9/78 -- '-' and '-p' options added (now fully |
| 148 | ** compatible with ttytype!), and spaces are |
| 149 | ** permitted between the -d and the type. |
| 150 | ** 8/78 -- The sense of -h and -u were reversed, and the |
| 151 | ** -f flag is dropped -- same effect is available |
| 152 | ** by just stating the terminal type. |
| 153 | ** 10/77 -- This version, in much it's previous state, |
| 154 | ** written by Eric Allman. |
| 155 | */ |
| 156 | |
| 157 | # define BACKSPACE ('H' & 037) |
| 158 | # define CONTROLX ('X' & 037) |
| 159 | # define OLDERASE '#' |
| 160 | # define OLDKILL '@' |
| 161 | |
| 162 | # define FILEDES 2 |
| 163 | # define STDOUT 1 |
| 164 | |
| 165 | # define DIALUP "du" |
| 166 | # define PLUGBOARD "pb" |
| 167 | # define BUSSIPLEXER "bx" |
| 168 | /* # define FULLLOGIN FULLLOGIN login does everything */ |
| 169 | # define VERSION7 VERSION7 /* version seven flag */ |
| 170 | # define GTTYN GTTYN /* general tty names */ |
| 171 | |
| 172 | # ifdef VERSION7 |
| 173 | # define UIDMASK 0177777 |
| 174 | # else |
| 175 | # define UIDMASK 0377 |
| 176 | # endif |
| 177 | |
| 178 | # ifdef GTTYN |
| 179 | typedef char *ttyid_t; |
| 180 | # else |
| 181 | typedef char ttyid_t; |
| 182 | # endif |
| 183 | |
| 184 | # define NOTTY 0 |
| 185 | |
| 186 | |
| 187 | |
| 188 | |
| 189 | |
| 190 | char Erase_char; /* new erase character */ |
| 191 | char Kill_char; /* new kill character */ |
| 192 | char Specialerase; /* set => Erase_char only on terminals with backspace */ |
| 193 | |
| 194 | ttyid_t Ttyid = NOTTY; /* terminal identifier */ |
| 195 | char *Ttytype; /* type of terminal */ |
| 196 | char *Dialtype; /* override type if dialup terminal */ |
| 197 | char *Plugtype; /* override type if plugboard port */ |
| 198 | char *Bxtype; /* override type if bussiplexer port */ |
| 199 | int Dash_u; /* don't-update-htmp flag */ |
| 200 | int Dash_h; /* don't-read-htmp flag */ |
| 201 | int Report; /* report current type */ |
| 202 | int Ureport; /* report to user */ |
| 203 | |
| 204 | char Usage[] = "usage: tset [-] [-r] [-eC] [-kC] [-d T] [-p T] [-b T] [-h] [-u] [type]\n"; |
| 205 | |
| 206 | char Capbuf[256]; /* line from /etc/ttycap for this Ttytype */ |
| 207 | |
| 208 | struct delay |
| 209 | { |
| 210 | int d_delay; |
| 211 | int d_bits; |
| 212 | }; |
| 213 | |
| 214 | # include "tset.del.h" |
| 215 | |
| 216 | |
| 217 | |
| 218 | main(argc, argv) |
| 219 | int argc; |
| 220 | char *argv[]; |
| 221 | { |
| 222 | struct sgttyb mode; |
| 223 | struct sgttyb oldmode; |
| 224 | char buf[256]; |
| 225 | auto char *bufp; |
| 226 | register char *p; |
| 227 | char *command; |
| 228 | register int i; |
| 229 | register int error; |
| 230 | int mdvect[2]; |
| 231 | extern char *stypeof(); |
| 232 | # ifndef VERSION7 |
| 233 | extern char *hsgettype(); |
| 234 | # else |
| 235 | extern char *getenv(); |
| 236 | # endif |
| 237 | # ifdef GTTYN |
| 238 | extern char *ttyname(); |
| 239 | # endif |
| 240 | |
| 241 | /* scan argument list and collect flags */ |
| 242 | error = 0; |
| 243 | command = argv[0]; |
| 244 | argc--; |
| 245 | while (--argc >= 0) |
| 246 | { |
| 247 | p = *++argv; |
| 248 | if (p[0] == '-') |
| 249 | { |
| 250 | switch (p[1]) |
| 251 | { |
| 252 | |
| 253 | case 0: /* report current terminal type */ |
| 254 | Report++; |
| 255 | continue; |
| 256 | |
| 257 | case 'r': /* report to user */ |
| 258 | Ureport++; |
| 259 | continue; |
| 260 | |
| 261 | case 'E': /* special erase: operate on all but TTY33 */ |
| 262 | Specialerase++; |
| 263 | /* exlicit fall-through to -e case */ |
| 264 | |
| 265 | case 'e': /* erase character */ |
| 266 | if (p[2] == 0) |
| 267 | Erase_char = BACKSPACE; |
| 268 | else |
| 269 | Erase_char = p[2]; |
| 270 | continue; |
| 271 | |
| 272 | case 'k': /* kill character */ |
| 273 | if (p[2] == 0) |
| 274 | Kill_char = CONTROLX; |
| 275 | else |
| 276 | Kill_char = p[2]; |
| 277 | continue; |
| 278 | |
| 279 | case 'd': /* dialup type */ |
| 280 | if (p[2] != 0) |
| 281 | Dialtype = &p[2]; |
| 282 | else if (--argc < 0 || argv[1][0] == '-') |
| 283 | error++; |
| 284 | else |
| 285 | Dialtype = *++argv; |
| 286 | continue; |
| 287 | |
| 288 | # ifdef PLUGBOARD |
| 289 | case 'p': /* plugboard type */ |
| 290 | if (p[2] != 0) |
| 291 | Plugtype = &p[2]; |
| 292 | else if (--argc < 0 || argv[1][0] == '-') |
| 293 | error++; |
| 294 | else |
| 295 | Plugtype = *++argv; |
| 296 | continue; |
| 297 | # endif |
| 298 | |
| 299 | # ifdef BUSSIPLEXER |
| 300 | case 'b': /* bussiplexer type */ |
| 301 | if (p[2] != 0) |
| 302 | Bxtype = &p[2]; |
| 303 | else if (--argc < 0 || argv[1][0] == '-') |
| 304 | error++; |
| 305 | else |
| 306 | Bxtype = *++argv; |
| 307 | # endif |
| 308 | |
| 309 | case 'h': /* don't get type from htmp */ |
| 310 | Dash_h++; |
| 311 | continue; |
| 312 | |
| 313 | # ifndef VERSION7 |
| 314 | case 'u': /* don't update htmp */ |
| 315 | Dash_u++; |
| 316 | continue; |
| 317 | # endif |
| 318 | |
| 319 | default: |
| 320 | prs("Bad flag "); |
| 321 | prs(p); |
| 322 | prs("\n"); |
| 323 | error++; |
| 324 | |
| 325 | } |
| 326 | } |
| 327 | else |
| 328 | { |
| 329 | /* terminal type */ |
| 330 | Ttytype = p; |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | if (error) |
| 335 | { |
| 336 | prs(Usage); |
| 337 | exit(1); |
| 338 | } |
| 339 | |
| 340 | # ifndef FULLLOGIN |
| 341 | /* if dialup is specified, check ttytype not htmp */ |
| 342 | if (Dialtype != 0 || Plugtype != 0 || Bxtype != 0) |
| 343 | Dash_h++; |
| 344 | # endif |
| 345 | |
| 346 | /* determine terminal id if needed */ |
| 347 | if (Ttyid == NOTTY && (Ttytype == 0 || !Dash_h || !Dash_u)) |
| 348 | # ifndef VERSION7 |
| 349 | Ttyid = ttyn(FILEDES); |
| 350 | # else |
| 351 | Ttyid = ttyname(FILEDES); |
| 352 | # endif |
| 353 | |
| 354 | # ifndef VERSION7 |
| 355 | /* get htmp if ever used */ |
| 356 | if (!Dash_u || (Ttytype == 0 && !Dash_h)) |
| 357 | { |
| 358 | /* get htmp entry */ |
| 359 | hget(Ttyid); |
| 360 | |
| 361 | /* if not for this user, look at ttytype file */ |
| 362 | if (hgettype() == 0 || hgetuid() != (getuid() & UIDMASK)) |
| 363 | Dash_h++; |
| 364 | } |
| 365 | # endif |
| 366 | |
| 367 | /* find terminal type (if not already known) */ |
| 368 | if (Ttytype == 0) |
| 369 | { |
| 370 | /* get type from /etc/ttytype or /etc/htmp */ |
| 371 | if (!Dash_h) |
| 372 | { |
| 373 | # ifndef VERSION7 |
| 374 | Ttytype = hsgettype(); |
| 375 | # else |
| 376 | Ttytype = getenv("TERM"); |
| 377 | # endif |
| 378 | } |
| 379 | if (Ttytype == 0) |
| 380 | { |
| 381 | Ttytype = stypeof(Ttyid); |
| 382 | } |
| 383 | |
| 384 | /* check for dialup or plugboard override */ |
| 385 | if (Dialtype != 0 && bequal(Ttytype, DIALUP, 2)) |
| 386 | Ttytype = Dialtype; |
| 387 | # ifdef PLUGBOARD |
| 388 | else if (Plugtype != 0 && bequal(Ttytype, PLUGBOARD, 2)) |
| 389 | Ttytype = Plugtype; |
| 390 | # endif |
| 391 | # ifdef BUSSIPLEXER |
| 392 | else if (Bxtype != 0 && bequal(Ttytype, BUSSIPLEXER, 2)) |
| 393 | Ttytype = Bxtype; |
| 394 | # endif |
| 395 | } |
| 396 | |
| 397 | /* Ttytype now contains a pointer to the type of the terminal */ |
| 398 | |
| 399 | if (gtty(FILEDES, &mode) < 0) |
| 400 | { |
| 401 | prs("Not a terminal\n"); |
| 402 | exit(1); |
| 403 | } |
| 404 | bmove(&mode, &oldmode, sizeof mode); |
| 405 | |
| 406 | /* get terminal capabilities */ |
| 407 | switch (tgetent(Capbuf, Ttytype)) |
| 408 | { |
| 409 | |
| 410 | case -1: |
| 411 | prs("Cannot open ttycap file\n"); |
| 412 | exit(-1); |
| 413 | |
| 414 | case 0: |
| 415 | prs("Type "); |
| 416 | prs(Ttytype); |
| 417 | prs(" unknown\n"); |
| 418 | exit(1); |
| 419 | } |
| 420 | |
| 421 | /* report type if appropriate */ |
| 422 | if (Report || Ureport) |
| 423 | { |
| 424 | /* find first alias (if any) */ |
| 425 | for (p = Capbuf; *p != 0 && *p != '|' && *p != ':'; p++) |
| 426 | continue; |
| 427 | if (*p == 0 || *p == ':') |
| 428 | p = Capbuf; |
| 429 | else |
| 430 | p++; |
| 431 | bufp = p; |
| 432 | while (*p != '|' && *p != ':' && *p != 0) |
| 433 | p++; |
| 434 | i = *p; |
| 435 | if (Report) |
| 436 | { |
| 437 | *p = '\n'; |
| 438 | write(STDOUT, bufp, p + 1 - bufp); |
| 439 | } |
| 440 | if (Ureport) |
| 441 | { |
| 442 | *p = '\0'; |
| 443 | prs("Terminal type is "); |
| 444 | prs(bufp); |
| 445 | prs("\n"); |
| 446 | } |
| 447 | *p = i; |
| 448 | } |
| 449 | |
| 450 | /* determine erase and kill characters */ |
| 451 | if (Specialerase && !tgetflag("bs")) |
| 452 | Erase_char = 0; |
| 453 | if (Erase_char == 0) |
| 454 | { |
| 455 | if (mode.sg_erase == 0) |
| 456 | mode.sg_erase = OLDERASE; |
| 457 | if (tgetflag("bs") && !tgetflag("os")) |
| 458 | mode.sg_erase = BACKSPACE; |
| 459 | } |
| 460 | else |
| 461 | mode.sg_erase = Erase_char; |
| 462 | |
| 463 | if (mode.sg_kill == 0) |
| 464 | mode.sg_kill = OLDKILL; |
| 465 | if (Kill_char != 0) |
| 466 | mode.sg_kill = Kill_char; |
| 467 | |
| 468 | /* set modes */ |
| 469 | setdelay("dC", CRdelay, CRbits, &mode.sg_flags); |
| 470 | setdelay("dN", NLdelay, NLbits, &mode.sg_flags); |
| 471 | setdelay("dB", BSdelay, BSbits, &mode.sg_flags); |
| 472 | setdelay("dF", FFdelay, FFbits, &mode.sg_flags); |
| 473 | setdelay("dT", TBdelay, TBbits, &mode.sg_flags); |
| 474 | if (tgetflag("UC") || command[0] == 'T') |
| 475 | mode.sg_flags |= LCASE; |
| 476 | else if (tgetflag("LC")) |
| 477 | mode.sg_flags &= ~LCASE; |
| 478 | mode.sg_flags &= ~(EVENP | ODDP | RAW); |
| 479 | if (tgetflag("EP")) |
| 480 | mode.sg_flags |= EVENP; |
| 481 | if (tgetflag("OP")) |
| 482 | mode.sg_flags |= ODDP; |
| 483 | if ((mode.sg_flags & (EVENP | ODDP)) == 0) |
| 484 | mode.sg_flags |= EVENP | ODDP; |
| 485 | mode.sg_flags |= CRMOD | ECHO | XTABS; |
| 486 | if (tgetflag("NL")) /* new line, not line feed */ |
| 487 | mode.sg_flags &= ~CRMOD; |
| 488 | if (tgetflag("HD")) /* half duplex */ |
| 489 | mode.sg_flags &= ~ECHO; |
| 490 | if (tgetflag("pt")) /* print tabs */ |
| 491 | mode.sg_flags &= ~XTABS; |
| 492 | # ifdef VERSION7 |
| 493 | if (!bequal(&mode, &oldmode, sizeof mode)) |
| 494 | ioctl(FILEDES, TIOCSETN, &mode); |
| 495 | # else |
| 496 | if (!bequal(&mode, &oldmode, sizeof mode)) |
| 497 | stty(FILEDES, &mode); |
| 498 | # endif |
| 499 | |
| 500 | /* output startup string */ |
| 501 | bufp = buf; |
| 502 | if (tgetstr("is", &bufp) != 0) |
| 503 | prs(buf); |
| 504 | bufp = buf; |
| 505 | if (tgetstr("if", &bufp) != 0) |
| 506 | cat(buf); |
| 507 | |
| 508 | /* tell about changing erase and kill characters */ |
| 509 | reportek("Erase", mode.sg_erase, oldmode.sg_erase, OLDERASE); |
| 510 | reportek("Kill", mode.sg_kill, oldmode.sg_kill, OLDKILL); |
| 511 | |
| 512 | # ifndef VERSION7 |
| 513 | /* update htmp */ |
| 514 | if (!Dash_u) |
| 515 | { |
| 516 | if (Ttyid == 0) |
| 517 | Ttyid = ttyn(FILEDES); |
| 518 | if (Ttyid == 'x') |
| 519 | prs("Cannot update htmp\n"); |
| 520 | else |
| 521 | { |
| 522 | /* update htmp file only if changed */ |
| 523 | if (!bequal(Capbuf, hsgettype(), 2)) |
| 524 | { |
| 525 | hsettype(Capbuf[0] | (Capbuf[1] << 8)); |
| 526 | hput(Ttyid); |
| 527 | } |
| 528 | } |
| 529 | } |
| 530 | # endif |
| 531 | |
| 532 | exit(0); |
| 533 | } |
| 534 | |
| 535 | |
| 536 | reportek(name, new, old, def) |
| 537 | char *name; |
| 538 | char old; |
| 539 | char new; |
| 540 | char def; |
| 541 | { |
| 542 | register char o; |
| 543 | register char n; |
| 544 | register char *p; |
| 545 | |
| 546 | o = old; |
| 547 | n = new; |
| 548 | |
| 549 | if (o == n && n == def) |
| 550 | return; |
| 551 | prs(name); |
| 552 | if (o == n) |
| 553 | prs(" is "); |
| 554 | else |
| 555 | prs(" set to "); |
| 556 | if (n < 040) |
| 557 | { |
| 558 | prs("control-"); |
| 559 | n = (n & 037) | 0100; |
| 560 | } |
| 561 | p = "x\n"; |
| 562 | p[0] = n; |
| 563 | prs(p); |
| 564 | } |
| 565 | |
| 566 | |
| 567 | |
| 568 | |
| 569 | setdelay(cap, dtab, bits, flags) |
| 570 | char *cap; |
| 571 | struct delay dtab[]; |
| 572 | int bits; |
| 573 | int *flags; |
| 574 | { |
| 575 | register int i; |
| 576 | register struct delay *p; |
| 577 | |
| 578 | /* see if this capability exists at all */ |
| 579 | i = tgetnum(cap); |
| 580 | if (i < 0) |
| 581 | i = 0; |
| 582 | |
| 583 | /* clear out the bits, replace with new ones */ |
| 584 | *flags &= ~bits; |
| 585 | |
| 586 | /* scan dtab for first entry with adequate delay */ |
| 587 | for (p = dtab; p->d_delay >= 0; p++) |
| 588 | { |
| 589 | if (p->d_delay >= i) |
| 590 | { |
| 591 | p++; |
| 592 | break; |
| 593 | } |
| 594 | } |
| 595 | |
| 596 | /* use last entry if none will do */ |
| 597 | *flags |= (--p)->d_bits; |
| 598 | } |
| 599 | |
| 600 | |
| 601 | prs(s) |
| 602 | char *s; |
| 603 | { |
| 604 | register char *p; |
| 605 | register char *q; |
| 606 | register int i; |
| 607 | |
| 608 | p = q = s; |
| 609 | i = 0; |
| 610 | while (*q++ != 0) |
| 611 | i++; |
| 612 | |
| 613 | if (i > 0) |
| 614 | write(FILEDES, p, i); |
| 615 | } |
| 616 | |
| 617 | |
| 618 | cat(file) |
| 619 | char *file; |
| 620 | { |
| 621 | register int fd; |
| 622 | register int i; |
| 623 | char buf[512]; |
| 624 | |
| 625 | fd = open(file, 0); |
| 626 | if (fd < 0) |
| 627 | { |
| 628 | prs("Cannot open "); |
| 629 | prs(file); |
| 630 | prs("\n"); |
| 631 | exit(-1); |
| 632 | } |
| 633 | |
| 634 | while ((i = read(fd, buf, 512)) > 0) |
| 635 | write(FILEDES, buf, i); |
| 636 | |
| 637 | close(fd); |
| 638 | } |
| 639 | |
| 640 | |
| 641 | |
| 642 | bmove(from, to, length) |
| 643 | char *from; |
| 644 | char *to; |
| 645 | int length; |
| 646 | { |
| 647 | register char *p, *q; |
| 648 | register int i; |
| 649 | |
| 650 | i = length; |
| 651 | p = from; |
| 652 | q = to; |
| 653 | |
| 654 | while (i-- > 0) |
| 655 | *q++ = *p++; |
| 656 | } |
| 657 | |
| 658 | |
| 659 | |
| 660 | bequal(a, b, len) |
| 661 | char *a; |
| 662 | char *b; |
| 663 | int len; |
| 664 | { |
| 665 | register char *p, *q; |
| 666 | register int i; |
| 667 | |
| 668 | i = len; |
| 669 | p = a; |
| 670 | q = b; |
| 671 | |
| 672 | while (i-- > 0) |
| 673 | if (*p++ != *q++) |
| 674 | return (0); |
| 675 | return (1); |
| 676 | } |