t_openpam_readword.c revision 236099
1236099Sdes/*- 2236099Sdes * Copyright (c) 2012 Dag-Erling Sm��rgrav 3236099Sdes * All rights reserved. 4236099Sdes * 5236099Sdes * Redistribution and use in source and binary forms, with or without 6236099Sdes * modification, are permitted provided that the following conditions 7236099Sdes * are met: 8236099Sdes * 1. Redistributions of source code must retain the above copyright 9236099Sdes * notice, this list of conditions and the following disclaimer 10236099Sdes * in this position and unchanged. 11236099Sdes * 2. Redistributions in binary form must reproduce the above copyright 12236099Sdes * notice, this list of conditions and the following disclaimer in the 13236099Sdes * documentation and/or other materials provided with the distribution. 14236099Sdes * 3. The name of the author may not be used to endorse or promote 15236099Sdes * products derived from this software without specific prior written 16236099Sdes * permission. 17236099Sdes * 18236099Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19236099Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20236099Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21236099Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22236099Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23236099Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24236099Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25236099Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26236099Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27236099Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28236099Sdes * SUCH DAMAGE. 29236099Sdes * 30236099Sdes * $Id: t_openpam_readword.c 584 2012-04-07 22:47:16Z des $ 31236099Sdes */ 32236099Sdes 33236099Sdes#ifdef HAVE_CONFIG_H 34236099Sdes# include "config.h" 35236099Sdes#endif 36236099Sdes 37236099Sdes#include <err.h> 38236099Sdes#include <errno.h> 39236099Sdes#include <fcntl.h> 40236099Sdes#include <stdio.h> 41236099Sdes#include <stdlib.h> 42236099Sdes#include <string.h> 43236099Sdes#include <unistd.h> 44236099Sdes 45236099Sdes#include <security/pam_appl.h> 46236099Sdes#include <security/openpam.h> 47236099Sdes 48236099Sdes#include "t.h" 49236099Sdes 50236099Sdesstatic char filename[1024]; 51236099Sdesstatic FILE *f; 52236099Sdes 53236099Sdes/* 54236099Sdes * Open the temp file and immediately unlink it so it doesn't leak in case 55236099Sdes * of premature exit. 56236099Sdes */ 57236099Sdesstatic void 58236099Sdesorw_open(void) 59236099Sdes{ 60236099Sdes int fd; 61236099Sdes 62236099Sdes if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) 63236099Sdes err(1, "%s(): %s", __func__, filename); 64236099Sdes if ((f = fdopen(fd, "r+")) == NULL) 65236099Sdes err(1, "%s(): %s", __func__, filename); 66236099Sdes if (unlink(filename) < 0) 67236099Sdes err(1, "%s(): %s", __func__, filename); 68236099Sdes} 69236099Sdes 70236099Sdes/* 71236099Sdes * Write text to the temp file. 72236099Sdes */ 73236099Sdesstatic void 74236099Sdesorw_output(const char *fmt, ...) 75236099Sdes{ 76236099Sdes va_list ap; 77236099Sdes 78236099Sdes va_start(ap, fmt); 79236099Sdes vfprintf(f, fmt, ap); 80236099Sdes va_end(ap); 81236099Sdes if (ferror(f)) 82236099Sdes err(1, "%s", filename); 83236099Sdes} 84236099Sdes 85236099Sdes/* 86236099Sdes * Rewind the temp file. 87236099Sdes */ 88236099Sdesstatic void 89236099Sdesorw_rewind(void) 90236099Sdes{ 91236099Sdes 92236099Sdes errno = 0; 93236099Sdes rewind(f); 94236099Sdes if (errno != 0) 95236099Sdes err(1, "%s(): %s", __func__, filename); 96236099Sdes} 97236099Sdes 98236099Sdes/* 99236099Sdes * Read a word from the temp file and verify that the result matches our 100236099Sdes * expectations: whether a word was read at all, how many lines were read 101236099Sdes * (in case of quoted or escaped newlines), whether we reached the end of 102236099Sdes * the file and whether we reached the end of the line. 103236099Sdes */ 104236099Sdesstatic int 105236099Sdesorw_expect(const char *expected, int lines, int eof, int eol) 106236099Sdes{ 107236099Sdes int ch, lineno = 0; 108236099Sdes char *got; 109236099Sdes size_t len; 110236099Sdes 111236099Sdes got = openpam_readword(f, &lineno, &len); 112236099Sdes if (ferror(f)) 113236099Sdes err(1, "%s(): %s", __func__, filename); 114236099Sdes if (expected != NULL && got == NULL) { 115236099Sdes t_verbose("expected <<%s>>, got nothing\n", expected); 116236099Sdes return (0); 117236099Sdes } 118236099Sdes if (expected == NULL && got != NULL) { 119236099Sdes t_verbose("expected nothing, got <<%s>>\n", got); 120236099Sdes return (0); 121236099Sdes } 122236099Sdes if (expected != NULL && got != NULL && strcmp(expected, got) != 0) { 123236099Sdes t_verbose("expected <<%s>>, got <<%s>>\n", expected, got); 124236099Sdes return (0); 125236099Sdes } 126236099Sdes if (lineno != lines) { 127236099Sdes t_verbose("expected to advance %d lines, advanced %d lines\n", 128236099Sdes lines, lineno); 129236099Sdes return (0); 130236099Sdes } 131236099Sdes if (eof && !feof(f)) { 132236099Sdes t_verbose("expected EOF, but didn't get it\n"); 133236099Sdes return (0); 134236099Sdes } 135236099Sdes if (!eof && feof(f)) { 136236099Sdes t_verbose("didn't expect EOF, but got it anyway\n"); 137236099Sdes return (0); 138236099Sdes } 139236099Sdes ch = fgetc(f); 140236099Sdes if (ferror(f)) 141236099Sdes err(1, "%s(): %s", __func__, filename); 142236099Sdes if (eol && ch != '\n') { 143236099Sdes t_verbose("expected EOL, but didn't get it\n"); 144236099Sdes return (0); 145236099Sdes } 146236099Sdes if (!eol && ch == '\n') { 147236099Sdes t_verbose("didn't expect EOL, but got it anyway\n"); 148236099Sdes return (0); 149236099Sdes } 150236099Sdes if (ch != EOF) 151236099Sdes ungetc(ch, f); 152236099Sdes return (1); 153236099Sdes} 154236099Sdes 155236099Sdes/* 156236099Sdes * Close the temp file. 157236099Sdes */ 158236099Sdesvoid 159236099Sdesorw_close(void) 160236099Sdes{ 161236099Sdes 162236099Sdes if (fclose(f) != 0) 163236099Sdes err(1, "%s(): %s", __func__, filename); 164236099Sdes f = NULL; 165236099Sdes} 166236099Sdes 167236099Sdes 168236099Sdes/*************************************************************************** 169236099Sdes * Lines without words 170236099Sdes */ 171236099Sdes 172236099SdesT_FUNC(empty_input, "empty input") 173236099Sdes{ 174236099Sdes int ret; 175236099Sdes 176236099Sdes orw_open(); 177236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 178236099Sdes orw_close(); 179236099Sdes return (ret); 180236099Sdes} 181236099Sdes 182236099SdesT_FUNC(empty_line, "empty line") 183236099Sdes{ 184236099Sdes int ret; 185236099Sdes 186236099Sdes orw_open(); 187236099Sdes orw_output("\n"); 188236099Sdes orw_rewind(); 189236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 190236099Sdes orw_close(); 191236099Sdes return (ret); 192236099Sdes} 193236099Sdes 194236099SdesT_FUNC(unterminated_line, "unterminated line") 195236099Sdes{ 196236099Sdes int ret; 197236099Sdes 198236099Sdes orw_open(); 199236099Sdes orw_output(" "); 200236099Sdes orw_rewind(); 201236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 202236099Sdes orw_close(); 203236099Sdes return (ret); 204236099Sdes} 205236099Sdes 206236099SdesT_FUNC(single_whitespace, "single whitespace") 207236099Sdes{ 208236099Sdes int ret; 209236099Sdes 210236099Sdes orw_open(); 211236099Sdes orw_output(" \n"); 212236099Sdes orw_rewind(); 213236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 214236099Sdes orw_close(); 215236099Sdes return (ret); 216236099Sdes} 217236099Sdes 218236099SdesT_FUNC(multiple_whitespace, "multiple whitespace") 219236099Sdes{ 220236099Sdes int ret; 221236099Sdes 222236099Sdes orw_open(); 223236099Sdes orw_output(" \t\r\n"); 224236099Sdes orw_rewind(); 225236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 226236099Sdes orw_close(); 227236099Sdes return (ret); 228236099Sdes} 229236099Sdes 230236099SdesT_FUNC(comment, "comment") 231236099Sdes{ 232236099Sdes int ret; 233236099Sdes 234236099Sdes orw_open(); 235236099Sdes orw_output("# comment\n"); 236236099Sdes orw_rewind(); 237236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 238236099Sdes orw_close(); 239236099Sdes return (ret); 240236099Sdes} 241236099Sdes 242236099SdesT_FUNC(whitespace_before_comment, "whitespace before comment") 243236099Sdes{ 244236099Sdes int ret; 245236099Sdes 246236099Sdes orw_open(); 247236099Sdes orw_output(" # comment\n"); 248236099Sdes orw_rewind(); 249236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 250236099Sdes orw_close(); 251236099Sdes return (ret); 252236099Sdes} 253236099Sdes 254236099Sdes 255236099Sdes/*************************************************************************** 256236099Sdes * Simple cases - no quotes or escapes 257236099Sdes */ 258236099Sdes 259236099SdesT_FUNC(single_word, "single word") 260236099Sdes{ 261236099Sdes const char *word = "hello"; 262236099Sdes int ret; 263236099Sdes 264236099Sdes orw_open(); 265236099Sdes orw_output("%s\n", word); 266236099Sdes orw_rewind(); 267236099Sdes ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 268236099Sdes orw_close(); 269236099Sdes return (ret); 270236099Sdes} 271236099Sdes 272236099SdesT_FUNC(single_whitespace_before_word, "single whitespace before word") 273236099Sdes{ 274236099Sdes const char *word = "hello"; 275236099Sdes int ret; 276236099Sdes 277236099Sdes orw_open(); 278236099Sdes orw_output(" %s\n", word); 279236099Sdes orw_rewind(); 280236099Sdes ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 281236099Sdes orw_close(); 282236099Sdes return (ret); 283236099Sdes} 284236099Sdes 285236099SdesT_FUNC(double_whitespace_before_word, "double whitespace before word") 286236099Sdes{ 287236099Sdes const char *word = "hello"; 288236099Sdes int ret; 289236099Sdes 290236099Sdes orw_open(); 291236099Sdes orw_output(" %s\n", word); 292236099Sdes orw_rewind(); 293236099Sdes ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 294236099Sdes orw_close(); 295236099Sdes return (ret); 296236099Sdes} 297236099Sdes 298236099SdesT_FUNC(single_whitespace_after_word, "single whitespace after word") 299236099Sdes{ 300236099Sdes const char *word = "hello"; 301236099Sdes int ret; 302236099Sdes 303236099Sdes orw_open(); 304236099Sdes orw_output("%s \n", word); 305236099Sdes orw_rewind(); 306236099Sdes ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 307236099Sdes orw_close(); 308236099Sdes return (ret); 309236099Sdes} 310236099Sdes 311236099SdesT_FUNC(double_whitespace_after_word, "double whitespace after word") 312236099Sdes{ 313236099Sdes const char *word = "hello"; 314236099Sdes int ret; 315236099Sdes 316236099Sdes orw_open(); 317236099Sdes orw_output("%s \n", word); 318236099Sdes orw_rewind(); 319236099Sdes ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 320236099Sdes orw_close(); 321236099Sdes return (ret); 322236099Sdes} 323236099Sdes 324236099SdesT_FUNC(comment_after_word, "comment after word") 325236099Sdes{ 326236099Sdes const char *word = "hello"; 327236099Sdes int ret; 328236099Sdes 329236099Sdes orw_open(); 330236099Sdes orw_output("%s # comment\n", word); 331236099Sdes orw_rewind(); 332236099Sdes ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 333236099Sdes orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 334236099Sdes orw_close(); 335236099Sdes return (ret); 336236099Sdes} 337236099Sdes 338236099SdesT_FUNC(word_containing_hash, "word containing hash") 339236099Sdes{ 340236099Sdes const char *word = "hello#world"; 341236099Sdes int ret; 342236099Sdes 343236099Sdes orw_open(); 344236099Sdes orw_output("%s\n", word); 345236099Sdes orw_rewind(); 346236099Sdes ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 347236099Sdes orw_close(); 348236099Sdes return (ret); 349236099Sdes} 350236099Sdes 351236099SdesT_FUNC(two_words, "two words") 352236099Sdes{ 353236099Sdes const char *word[] = { "hello", "world" }; 354236099Sdes int ret; 355236099Sdes 356236099Sdes orw_open(); 357236099Sdes orw_output("%s %s\n", word[0], word[1]); 358236099Sdes orw_rewind(); 359236099Sdes ret = orw_expect(word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 360236099Sdes orw_expect(word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 361236099Sdes orw_close(); 362236099Sdes return (ret); 363236099Sdes} 364236099Sdes 365236099Sdes 366236099Sdes/*************************************************************************** 367236099Sdes * Escapes 368236099Sdes */ 369236099Sdes 370236099SdesT_FUNC(naked_escape, "naked escape") 371236099Sdes{ 372236099Sdes int ret; 373236099Sdes 374236099Sdes orw_open(); 375236099Sdes orw_output("\\"); 376236099Sdes orw_rewind(); 377236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 378236099Sdes orw_close(); 379236099Sdes return (ret); 380236099Sdes} 381236099Sdes 382236099SdesT_FUNC(escaped_escape, "escaped escape") 383236099Sdes{ 384236099Sdes int ret; 385236099Sdes 386236099Sdes orw_open(); 387236099Sdes orw_output("\\\\\n"); 388236099Sdes orw_rewind(); 389236099Sdes ret = orw_expect("\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 390236099Sdes orw_close(); 391236099Sdes return (ret); 392236099Sdes} 393236099Sdes 394236099SdesT_FUNC(escaped_whitespace, "escaped whitespace") 395236099Sdes{ 396236099Sdes int ret; 397236099Sdes 398236099Sdes orw_open(); 399236099Sdes orw_output("\\ \\\t \\\r \\\n\n"); 400236099Sdes orw_rewind(); 401236099Sdes ret = orw_expect(" ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 402236099Sdes orw_expect("\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 403236099Sdes orw_expect("\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 404236099Sdes /* this last one is a line continuation */ 405236099Sdes orw_expect(NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 406236099Sdes orw_close(); 407236099Sdes return (ret); 408236099Sdes} 409236099Sdes 410236099SdesT_FUNC(escaped_newline_before_word, "escaped newline before word") 411236099Sdes{ 412236099Sdes int ret; 413236099Sdes 414236099Sdes orw_open(); 415236099Sdes orw_output("\\\nhello world\n"); 416236099Sdes orw_rewind(); 417236099Sdes ret = orw_expect("hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 418236099Sdes orw_close(); 419236099Sdes return (ret); 420236099Sdes} 421236099Sdes 422236099SdesT_FUNC(escaped_newline_within_word, "escaped newline within word") 423236099Sdes{ 424236099Sdes int ret; 425236099Sdes 426236099Sdes orw_open(); 427236099Sdes orw_output("hello\\\nworld\n"); 428236099Sdes orw_rewind(); 429236099Sdes ret = orw_expect("helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 430236099Sdes orw_close(); 431236099Sdes return (ret); 432236099Sdes} 433236099Sdes 434236099SdesT_FUNC(escaped_newline_after_word, "escaped newline after word") 435236099Sdes{ 436236099Sdes int ret; 437236099Sdes 438236099Sdes orw_open(); 439236099Sdes orw_output("hello\\\n world\n"); 440236099Sdes orw_rewind(); 441236099Sdes ret = orw_expect("hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 442236099Sdes orw_close(); 443236099Sdes return (ret); 444236099Sdes} 445236099Sdes 446236099SdesT_FUNC(escaped_letter, "escaped letter") 447236099Sdes{ 448236099Sdes int ret; 449236099Sdes 450236099Sdes orw_open(); 451236099Sdes orw_output("\\z\n"); 452236099Sdes orw_rewind(); 453236099Sdes ret = orw_expect("z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 454236099Sdes orw_close(); 455236099Sdes return (ret); 456236099Sdes} 457236099Sdes 458236099Sdes 459236099Sdes/*************************************************************************** 460236099Sdes * Quotes 461236099Sdes */ 462236099Sdes 463236099SdesT_FUNC(naked_single_quote, "naked single quote") 464236099Sdes{ 465236099Sdes int ret; 466236099Sdes 467236099Sdes orw_open(); 468236099Sdes orw_output("'"); 469236099Sdes orw_rewind(); 470236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 471236099Sdes orw_close(); 472236099Sdes return (ret); 473236099Sdes} 474236099Sdes 475236099SdesT_FUNC(naked_double_quote, "naked double quote") 476236099Sdes{ 477236099Sdes int ret; 478236099Sdes 479236099Sdes orw_open(); 480236099Sdes orw_output("\""); 481236099Sdes orw_rewind(); 482236099Sdes ret = orw_expect(NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 483236099Sdes orw_close(); 484236099Sdes return (ret); 485236099Sdes} 486236099Sdes 487236099SdesT_FUNC(empty_single_quotes, "empty single quotes") 488236099Sdes{ 489236099Sdes int ret; 490236099Sdes 491236099Sdes orw_open(); 492236099Sdes orw_output("''\n"); 493236099Sdes orw_rewind(); 494236099Sdes ret = orw_expect("", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 495236099Sdes orw_close(); 496236099Sdes return (ret); 497236099Sdes} 498236099Sdes 499236099SdesT_FUNC(empty_double_quotes, "empty double quotes") 500236099Sdes{ 501236099Sdes int ret; 502236099Sdes 503236099Sdes orw_open(); 504236099Sdes orw_output("\"\"\n"); 505236099Sdes orw_rewind(); 506236099Sdes ret = orw_expect("", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 507236099Sdes orw_close(); 508236099Sdes return (ret); 509236099Sdes} 510236099Sdes 511236099SdesT_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes") 512236099Sdes{ 513236099Sdes int ret; 514236099Sdes 515236099Sdes orw_open(); 516236099Sdes orw_output("\"' '\"\n"); 517236099Sdes orw_rewind(); 518236099Sdes ret = orw_expect("' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 519236099Sdes orw_close(); 520236099Sdes return (ret); 521236099Sdes} 522236099Sdes 523236099SdesT_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes") 524236099Sdes{ 525236099Sdes int ret; 526236099Sdes 527236099Sdes orw_open(); 528236099Sdes orw_output("'\" \"'\n"); 529236099Sdes orw_rewind(); 530236099Sdes ret = orw_expect("\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 531236099Sdes orw_close(); 532236099Sdes return (ret); 533236099Sdes} 534236099Sdes 535236099SdesT_FUNC(single_quoted_whitespace, "single-quoted whitespace") 536236099Sdes{ 537236099Sdes int ret; 538236099Sdes 539236099Sdes orw_open(); 540236099Sdes orw_output("' ' '\t' '\r' '\n'\n"); 541236099Sdes orw_rewind(); 542236099Sdes ret = orw_expect(" ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 543236099Sdes orw_expect("\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 544236099Sdes orw_expect("\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 545236099Sdes orw_expect("\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 546236099Sdes orw_close(); 547236099Sdes return (ret); 548236099Sdes} 549236099Sdes 550236099SdesT_FUNC(double_quoted_whitespace, "double-quoted whitespace") 551236099Sdes{ 552236099Sdes int ret; 553236099Sdes 554236099Sdes orw_open(); 555236099Sdes orw_output("\" \" \"\t\" \"\r\" \"\n\"\n"); 556236099Sdes orw_rewind(); 557236099Sdes ret = orw_expect(" ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 558236099Sdes orw_expect("\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 559236099Sdes orw_expect("\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 560236099Sdes orw_expect("\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 561236099Sdes orw_close(); 562236099Sdes return (ret); 563236099Sdes} 564236099Sdes 565236099SdesT_FUNC(single_quoted_words, "single-quoted words") 566236099Sdes{ 567236099Sdes int ret; 568236099Sdes 569236099Sdes orw_open(); 570236099Sdes orw_output("'hello world'\n"); 571236099Sdes orw_rewind(); 572236099Sdes ret = orw_expect("hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 573236099Sdes orw_close(); 574236099Sdes return (ret); 575236099Sdes} 576236099Sdes 577236099SdesT_FUNC(double_quoted_words, "double-quoted words") 578236099Sdes{ 579236099Sdes int ret; 580236099Sdes 581236099Sdes orw_open(); 582236099Sdes orw_output("\"hello world\"\n"); 583236099Sdes orw_rewind(); 584236099Sdes ret = orw_expect("hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 585236099Sdes orw_close(); 586236099Sdes return (ret); 587236099Sdes} 588236099Sdes 589236099Sdes 590236099Sdes/*************************************************************************** 591236099Sdes * Combinations of escape and quotes 592236099Sdes */ 593236099Sdes 594236099SdesT_FUNC(escaped_single_quote, 595236099Sdes "escaped single quote") 596236099Sdes{ 597236099Sdes int ret; 598236099Sdes 599236099Sdes orw_open(); 600236099Sdes orw_output("\\'\n"); 601236099Sdes orw_rewind(); 602236099Sdes ret = orw_expect("'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 603236099Sdes orw_close(); 604236099Sdes return (ret); 605236099Sdes} 606236099Sdes 607236099SdesT_FUNC(escaped_double_quote, 608236099Sdes "escaped double quote") 609236099Sdes{ 610236099Sdes int ret; 611236099Sdes 612236099Sdes orw_open(); 613236099Sdes orw_output("\\\"\n"); 614236099Sdes orw_rewind(); 615236099Sdes ret = orw_expect("\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 616236099Sdes orw_close(); 617236099Sdes return (ret); 618236099Sdes} 619236099Sdes 620236099SdesT_FUNC(escaped_whitespace_within_single_quotes, 621236099Sdes "escaped whitespace within single quotes") 622236099Sdes{ 623236099Sdes int ret; 624236099Sdes 625236099Sdes orw_open(); 626236099Sdes orw_output("'\\ ' '\\\t' '\\\r' '\\\n'\n"); 627236099Sdes orw_rewind(); 628236099Sdes ret = orw_expect("\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 629236099Sdes orw_expect("\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 630236099Sdes orw_expect("\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 631236099Sdes orw_expect("\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 632236099Sdes orw_close(); 633236099Sdes return (ret); 634236099Sdes} 635236099Sdes 636236099SdesT_FUNC(escaped_whitespace_within_double_quotes, 637236099Sdes "escaped whitespace within double quotes") 638236099Sdes{ 639236099Sdes int ret; 640236099Sdes 641236099Sdes orw_open(); 642236099Sdes orw_output("\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n"); 643236099Sdes orw_rewind(); 644236099Sdes ret = orw_expect("\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 645236099Sdes orw_expect("\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 646236099Sdes orw_expect("\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 647236099Sdes /* this last one is a line continuation */ 648236099Sdes orw_expect("", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 649236099Sdes orw_close(); 650236099Sdes return (ret); 651236099Sdes} 652236099Sdes 653236099SdesT_FUNC(escaped_letter_within_single_quotes, 654236099Sdes "escaped letter within single quotes") 655236099Sdes{ 656236099Sdes int ret; 657236099Sdes 658236099Sdes orw_open(); 659236099Sdes orw_output("'\\z'\n"); 660236099Sdes orw_rewind(); 661236099Sdes ret = orw_expect("\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 662236099Sdes orw_close(); 663236099Sdes return (ret); 664236099Sdes} 665236099Sdes 666236099SdesT_FUNC(escaped_letter_within_double_quotes, 667236099Sdes "escaped letter within double quotes") 668236099Sdes{ 669236099Sdes int ret; 670236099Sdes 671236099Sdes orw_open(); 672236099Sdes orw_output("\"\\z\"\n"); 673236099Sdes orw_rewind(); 674236099Sdes ret = orw_expect("\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 675236099Sdes orw_close(); 676236099Sdes return (ret); 677236099Sdes} 678236099Sdes 679236099SdesT_FUNC(escaped_escape_within_single_quotes, 680236099Sdes "escaped escape within single quotes") 681236099Sdes{ 682236099Sdes int ret; 683236099Sdes 684236099Sdes orw_open(); 685236099Sdes orw_output("'\\\\'\n"); 686236099Sdes orw_rewind(); 687236099Sdes ret = orw_expect("\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 688236099Sdes orw_close(); 689236099Sdes return (ret); 690236099Sdes} 691236099Sdes 692236099SdesT_FUNC(escaped_escape_within_double_quotes, 693236099Sdes "escaped escape within double quotes") 694236099Sdes{ 695236099Sdes int ret; 696236099Sdes 697236099Sdes orw_open(); 698236099Sdes orw_output("\"\\\\\"\n"); 699236099Sdes orw_rewind(); 700236099Sdes ret = orw_expect("\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 701236099Sdes orw_close(); 702236099Sdes return (ret); 703236099Sdes} 704236099Sdes 705236099SdesT_FUNC(escaped_single_quote_within_single_quotes, 706236099Sdes "escaped single quote within single quotes") 707236099Sdes{ 708236099Sdes int ret; 709236099Sdes 710236099Sdes orw_open(); 711236099Sdes orw_output("'\\''\n"); 712236099Sdes orw_rewind(); 713236099Sdes ret = orw_expect(NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/); 714236099Sdes orw_close(); 715236099Sdes return (ret); 716236099Sdes} 717236099Sdes 718236099SdesT_FUNC(escaped_double_quote_within_single_quotes, 719236099Sdes "escaped double quote within single quotes") 720236099Sdes{ 721236099Sdes int ret; 722236099Sdes 723236099Sdes orw_open(); 724236099Sdes orw_output("'\\\"'\n"); 725236099Sdes orw_rewind(); 726236099Sdes ret = orw_expect("\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 727236099Sdes orw_close(); 728236099Sdes return (ret); 729236099Sdes} 730236099Sdes 731236099SdesT_FUNC(escaped_single_quote_within_double_quotes, 732236099Sdes "escaped single quote within double quotes") 733236099Sdes{ 734236099Sdes int ret; 735236099Sdes 736236099Sdes orw_open(); 737236099Sdes orw_output("\"\\'\"\n"); 738236099Sdes orw_rewind(); 739236099Sdes ret = orw_expect("\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 740236099Sdes orw_close(); 741236099Sdes return (ret); 742236099Sdes} 743236099Sdes 744236099SdesT_FUNC(escaped_double_quote_within_double_quotes, 745236099Sdes "escaped double quote within double quotes") 746236099Sdes{ 747236099Sdes int ret; 748236099Sdes 749236099Sdes orw_open(); 750236099Sdes orw_output("\"\\\"\"\n"); 751236099Sdes orw_rewind(); 752236099Sdes ret = orw_expect("\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 753236099Sdes orw_close(); 754236099Sdes return (ret); 755236099Sdes} 756236099Sdes 757236099Sdes 758236099Sdes/*************************************************************************** 759236099Sdes * Boilerplate 760236099Sdes */ 761236099Sdes 762236099Sdesconst struct t_test *t_plan[] = { 763236099Sdes T(empty_input), 764236099Sdes T(empty_line), 765236099Sdes T(single_whitespace), 766236099Sdes T(multiple_whitespace), 767236099Sdes T(comment), 768236099Sdes T(whitespace_before_comment), 769236099Sdes 770236099Sdes T(single_word), 771236099Sdes T(single_whitespace_before_word), 772236099Sdes T(double_whitespace_before_word), 773236099Sdes T(single_whitespace_after_word), 774236099Sdes T(double_whitespace_after_word), 775236099Sdes T(comment_after_word), 776236099Sdes T(word_containing_hash), 777236099Sdes T(two_words), 778236099Sdes 779236099Sdes T(naked_escape), 780236099Sdes T(escaped_escape), 781236099Sdes T(escaped_whitespace), 782236099Sdes T(escaped_newline_before_word), 783236099Sdes T(escaped_newline_within_word), 784236099Sdes T(escaped_newline_after_word), 785236099Sdes T(escaped_letter), 786236099Sdes 787236099Sdes T(naked_single_quote), 788236099Sdes T(naked_double_quote), 789236099Sdes T(empty_single_quotes), 790236099Sdes T(empty_double_quotes), 791236099Sdes T(single_quotes_within_double_quotes), 792236099Sdes T(double_quotes_within_single_quotes), 793236099Sdes T(single_quoted_whitespace), 794236099Sdes T(double_quoted_whitespace), 795236099Sdes T(single_quoted_words), 796236099Sdes T(double_quoted_words), 797236099Sdes 798236099Sdes T(escaped_single_quote), 799236099Sdes T(escaped_double_quote), 800236099Sdes T(escaped_whitespace_within_single_quotes), 801236099Sdes T(escaped_whitespace_within_double_quotes), 802236099Sdes T(escaped_letter_within_single_quotes), 803236099Sdes T(escaped_letter_within_double_quotes), 804236099Sdes T(escaped_escape_within_single_quotes), 805236099Sdes T(escaped_escape_within_double_quotes), 806236099Sdes T(escaped_single_quote_within_single_quotes), 807236099Sdes T(escaped_double_quote_within_single_quotes), 808236099Sdes T(escaped_single_quote_within_double_quotes), 809236099Sdes T(escaped_double_quote_within_double_quotes), 810236099Sdes 811236099Sdes NULL 812236099Sdes}; 813236099Sdes 814236099Sdesconst struct t_test ** 815236099Sdest_prepare(int argc, char *argv[]) 816236099Sdes{ 817236099Sdes 818236099Sdes (void)argc; 819236099Sdes (void)argv; 820236099Sdes snprintf(filename, sizeof filename, "%s.%d.tmp", t_progname, getpid()); 821236099Sdes if (filename == NULL) 822236099Sdes err(1, "asprintf()"); 823236099Sdes return (t_plan); 824236099Sdes} 825236099Sdes 826236099Sdesvoid 827236099Sdest_cleanup(void) 828236099Sdes{ 829236099Sdes} 830