11590Srgrimes/* 21590Srgrimes * Copyright (c) 1989, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Adam S. Moskowitz of Menlo Consulting. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 4. Neither the name of the University nor the names of its contributors 171590Srgrimes * may be used to endorse or promote products derived from this software 181590Srgrimes * without specific prior written permission. 191590Srgrimes * 201590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301590Srgrimes * SUCH DAMAGE. 311590Srgrimes */ 321590Srgrimes 331590Srgrimes#ifndef lint 3427787Scharnierstatic const char copyright[] = 351590Srgrimes"@(#) Copyright (c) 1989, 1993\n\ 361590Srgrimes The Regents of the University of California. All rights reserved.\n"; 371590Srgrimes#endif /* not lint */ 381590Srgrimes 3992772Smike#if 0 401590Srgrimes#ifndef lint 411590Srgrimesstatic char sccsid[] = "@(#)paste.c 8.1 (Berkeley) 6/6/93"; 4292772Smike#endif /* not lint */ 4327787Scharnier#endif 441590Srgrimes 4592772Smike#include <sys/cdefs.h> 4692772Smike__FBSDID("$FreeBSD$"); 4792772Smike 481590Srgrimes#include <sys/types.h> 4995626Smarkm 5027787Scharnier#include <err.h> 51200462Sdelphij#include <errno.h> 52200462Sdelphij#include <limits.h> 53131076Stjr#include <locale.h> 541590Srgrimes#include <stdio.h> 5533644Sjb#include <stdlib.h> 56200462Sdelphij#include <string.h> 5727787Scharnier#include <unistd.h> 58131076Stjr#include <wchar.h> 591590Srgrimes 60227242Sedstatic wchar_t *delim; 61227242Sedstatic int delimcnt; 621590Srgrimes 63227242Sedstatic int parallel(char **); 64227242Sedstatic int sequential(char **); 65227242Sedstatic int tr(wchar_t *); 6692921Simpstatic void usage(void); 6727787Scharnier 68227242Sedstatic wchar_t tab[] = L"\t"; 6995626Smarkm 7027787Scharnierint 7195626Smarkmmain(int argc, char *argv[]) 721590Srgrimes{ 7397223Stjr int ch, rval, seq; 74131076Stjr wchar_t *warg; 75131076Stjr const char *arg; 76131076Stjr size_t len; 771590Srgrimes 78131076Stjr setlocale(LC_CTYPE, ""); 79131076Stjr 801590Srgrimes seq = 0; 8124360Simp while ((ch = getopt(argc, argv, "d:s")) != -1) 821590Srgrimes switch(ch) { 831590Srgrimes case 'd': 84131076Stjr arg = optarg; 85131076Stjr len = mbsrtowcs(NULL, &arg, 0, NULL); 86131076Stjr if (len == (size_t)-1) 87131076Stjr err(1, "delimiters"); 88131076Stjr warg = malloc((len + 1) * sizeof(*warg)); 89131076Stjr if (warg == NULL) 90131076Stjr err(1, NULL); 91131076Stjr arg = optarg; 92131076Stjr len = mbsrtowcs(warg, &arg, len + 1, NULL); 93131076Stjr if (len == (size_t)-1) 94131076Stjr err(1, "delimiters"); 95131076Stjr delimcnt = tr(delim = warg); 961590Srgrimes break; 971590Srgrimes case 's': 981590Srgrimes seq = 1; 991590Srgrimes break; 1001590Srgrimes case '?': 1011590Srgrimes default: 1021590Srgrimes usage(); 1031590Srgrimes } 1041590Srgrimes argc -= optind; 1051590Srgrimes argv += optind; 1061590Srgrimes 10792772Smike if (*argv == NULL) 10892772Smike usage(); 1091590Srgrimes if (!delim) { 1101590Srgrimes delimcnt = 1; 11195626Smarkm delim = tab; 1121590Srgrimes } 1131590Srgrimes 1141590Srgrimes if (seq) 11597223Stjr rval = sequential(argv); 1161590Srgrimes else 11797223Stjr rval = parallel(argv); 11897223Stjr exit(rval); 1191590Srgrimes} 1201590Srgrimes 1211590Srgrimestypedef struct _list { 1221590Srgrimes struct _list *next; 1231590Srgrimes FILE *fp; 1241590Srgrimes int cnt; 1251590Srgrimes char *name; 1261590Srgrimes} LIST; 1271590Srgrimes 128227242Sedstatic int 12995626Smarkmparallel(char **argv) 1301590Srgrimes{ 13195626Smarkm LIST *lp; 13297233Stjr int cnt; 133131076Stjr wint_t ich; 134131076Stjr wchar_t ch; 135131076Stjr char *p; 1361590Srgrimes LIST *head, *tmp; 1371590Srgrimes int opencnt, output; 1381590Srgrimes 139162239Scharnier for (cnt = 0, head = tmp = NULL; (p = *argv); ++argv, ++cnt) { 14096785Sjmallett if ((lp = malloc(sizeof(LIST))) == NULL) 14196785Sjmallett err(1, NULL); 1421590Srgrimes if (p[0] == '-' && !p[1]) 1431590Srgrimes lp->fp = stdin; 14427787Scharnier else if (!(lp->fp = fopen(p, "r"))) 14527787Scharnier err(1, "%s", p); 1461590Srgrimes lp->next = NULL; 1471590Srgrimes lp->cnt = cnt; 1481590Srgrimes lp->name = p; 1491590Srgrimes if (!head) 1501590Srgrimes head = tmp = lp; 1511590Srgrimes else { 1521590Srgrimes tmp->next = lp; 1531590Srgrimes tmp = lp; 1541590Srgrimes } 1551590Srgrimes } 1561590Srgrimes 1571590Srgrimes for (opencnt = cnt; opencnt;) { 1581590Srgrimes for (output = 0, lp = head; lp; lp = lp->next) { 1591590Srgrimes if (!lp->fp) { 1601590Srgrimes if (output && lp->cnt && 1611590Srgrimes (ch = delim[(lp->cnt - 1) % delimcnt])) 162131076Stjr putwchar(ch); 1631590Srgrimes continue; 1641590Srgrimes } 165131076Stjr if ((ich = getwc(lp->fp)) == WEOF) { 1661590Srgrimes if (!--opencnt) 1671590Srgrimes break; 1681590Srgrimes lp->fp = NULL; 1691590Srgrimes if (output && lp->cnt && 1701590Srgrimes (ch = delim[(lp->cnt - 1) % delimcnt])) 171131076Stjr putwchar(ch); 1721590Srgrimes continue; 1731590Srgrimes } 1741590Srgrimes /* 1751590Srgrimes * make sure that we don't print any delimiters 1761590Srgrimes * unless there's a non-empty file. 1771590Srgrimes */ 1781590Srgrimes if (!output) { 1791590Srgrimes output = 1; 1801590Srgrimes for (cnt = 0; cnt < lp->cnt; ++cnt) 18127787Scharnier if ((ch = delim[cnt % delimcnt])) 182131076Stjr putwchar(ch); 18327787Scharnier } else if ((ch = delim[(lp->cnt - 1) % delimcnt])) 184131076Stjr putwchar(ch); 185131076Stjr if (ich == '\n') 186131076Stjr continue; 187131076Stjr do { 188131076Stjr putwchar(ich); 189131076Stjr } while ((ich = getwc(lp->fp)) != WEOF && ich != '\n'); 1901590Srgrimes } 1911590Srgrimes if (output) 192131076Stjr putwchar('\n'); 1931590Srgrimes } 19497223Stjr 19597223Stjr return (0); 1961590Srgrimes} 1971590Srgrimes 198227242Sedstatic int 19995626Smarkmsequential(char **argv) 2001590Srgrimes{ 20195626Smarkm FILE *fp; 20297233Stjr int cnt, failed, needdelim; 203131076Stjr wint_t ch; 204131076Stjr char *p; 2051590Srgrimes 20697223Stjr failed = 0; 20727787Scharnier for (; (p = *argv); ++argv) { 2081590Srgrimes if (p[0] == '-' && !p[1]) 2091590Srgrimes fp = stdin; 2101590Srgrimes else if (!(fp = fopen(p, "r"))) { 21127787Scharnier warn("%s", p); 21297223Stjr failed = 1; 2131590Srgrimes continue; 2141590Srgrimes } 21597230Stjr cnt = needdelim = 0; 216131076Stjr while ((ch = getwc(fp)) != WEOF) { 21797230Stjr if (needdelim) { 21897230Stjr needdelim = 0; 21997230Stjr if (delim[cnt] != '\0') 220131076Stjr putwchar(delim[cnt]); 22197230Stjr if (++cnt == delimcnt) 2221590Srgrimes cnt = 0; 2231590Srgrimes } 224131076Stjr if (ch != '\n') 225131076Stjr putwchar(ch); 226131076Stjr else 227131076Stjr needdelim = 1; 22897230Stjr } 22997230Stjr if (needdelim) 230131076Stjr putwchar('\n'); 2311590Srgrimes if (fp != stdin) 2321590Srgrimes (void)fclose(fp); 2331590Srgrimes } 23497223Stjr 23597223Stjr return (failed != 0); 2361590Srgrimes} 2371590Srgrimes 238227242Sedstatic int 239131076Stjrtr(wchar_t *arg) 2401590Srgrimes{ 24195626Smarkm int cnt; 242131076Stjr wchar_t ch, *p; 2431590Srgrimes 2441590Srgrimes for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt) 2451590Srgrimes if (ch == '\\') 2461590Srgrimes switch(ch = *p++) { 2471590Srgrimes case 'n': 2481590Srgrimes *arg = '\n'; 2491590Srgrimes break; 2501590Srgrimes case 't': 2511590Srgrimes *arg = '\t'; 2521590Srgrimes break; 2531590Srgrimes case '0': 2541590Srgrimes *arg = '\0'; 2551590Srgrimes break; 2561590Srgrimes default: 2571590Srgrimes *arg = ch; 2581590Srgrimes break; 2591590Srgrimes } else 2601590Srgrimes *arg = ch; 2611590Srgrimes 26227787Scharnier if (!cnt) 26327787Scharnier errx(1, "no delimiters specified"); 2641590Srgrimes return(cnt); 2651590Srgrimes} 2661590Srgrimes 26727787Scharnierstatic void 26895626Smarkmusage(void) 2691590Srgrimes{ 27027787Scharnier (void)fprintf(stderr, "usage: paste [-s] [-d delimiters] file ...\n"); 2711590Srgrimes exit(1); 2721590Srgrimes} 273