(root)/
util-linux-2.39/
include/
carefulputc.h
       1  #ifndef UTIL_LINUX_CAREFULPUTC_H
       2  #define UTIL_LINUX_CAREFULPUTC_H
       3  
       4  #include <stdio.h>
       5  #include <string.h>
       6  #include <ctype.h>
       7  #ifdef HAVE_WIDECHAR
       8  #include <wctype.h>
       9  #include <wchar.h>
      10  #endif
      11  #include <stdbool.h>
      12  
      13  #include "cctype.h"
      14  
      15  /*
      16   * A puts() for use in write and wall (that sometimes are sgid tty).
      17   * It avoids control and invalid characters.
      18   * The locale of the recipient is nominally unknown,
      19   * but it's a solid bet that it's compatible with the author's.
      20   * Use soft_width=0 to disable wrapping.
      21   */
      22  static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool cr_lf, int soft_width)
      23  {
      24  	int ret = 0, col = 0;
      25  
      26  	for (size_t slen = strlen(s); *s; ++s, --slen) {
      27  		if (*s == '\t')
      28  			col += (7 - (col % 8)) - 1;
      29  		else if (*s == '\r')
      30  			col = -1;
      31  		else if (*s == '\a')
      32  			--col;
      33  
      34  		if ((soft_width && col >= soft_width) || *s == '\n') {
      35  			if (soft_width) {
      36  				fprintf(fp, "%*s", soft_width - col, "");
      37  				col = 0;
      38  			}
      39  			ret = fputs(cr_lf ? "\r\n" : "\n", fp);
      40  			if (*s == '\n' || ret < 0)
      41  				goto wrote;
      42  		}
      43  
      44  		if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') {
      45  			ret = putc(*s, fp);
      46  			++col;
      47  		} else if (!c_isascii(*s)) {
      48  #ifdef HAVE_WIDECHAR
      49  			wchar_t w;
      50  			size_t clen = mbtowc(&w, s, slen);
      51  			switch(clen) {
      52  				case (size_t)-2:  // incomplete
      53  				case (size_t)-1:  // EILSEQ
      54  					mbtowc(NULL, NULL, 0);
      55  				nonprint:
      56  					col += ret = fprintf(fp, "\\%3hho", *s);
      57  					break;
      58  				default:
      59  					if(!iswprint(w))
      60  						goto nonprint;
      61  					ret = fwrite(s, 1, clen, fp);
      62  					if (soft_width)
      63  						col += wcwidth(w);
      64  					s += clen - 1;
      65  					slen -= clen - 1;
      66  					break;
      67  			}
      68  #else
      69  			col += ret = fprintf(fp, "\\%3hho", *s);
      70  #endif
      71  		} else {
      72  			ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp);
      73  			col += 2;
      74  		}
      75  
      76  	wrote:
      77  		if (ret < 0)
      78  			return EOF;
      79  	}
      80  	return 0;
      81  }
      82  
      83  static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
      84  {
      85  	const char *p;
      86  
      87  	fputc('"', out);
      88  	for (p = data; p && *p; p++) {
      89  		if ((unsigned char) *p == 0x22 ||		/* " */
      90  		    (unsigned char) *p == 0x5c ||		/* \ */
      91  		    (unsigned char) *p == 0x60 ||		/* ` */
      92  		    (unsigned char) *p == 0x24 ||		/* $ */
      93  		    !isprint((unsigned char) *p) ||
      94  		    iscntrl((unsigned char) *p)) {
      95  
      96  			fprintf(out, "\\x%02x", (unsigned char) *p);
      97  		} else
      98  			fputc(dir ==  1 ? toupper(*p) :
      99  			      dir == -1 ? tolower(*p) :
     100  			      *p, out);
     101  	}
     102  	fputc('"', out);
     103  }
     104  
     105  #define fputs_quoted(_d, _o)		fputs_quoted_case(_d, _o, 0)
     106  #define fputs_quoted_upper(_d, _o)	fputs_quoted_case(_d, _o, 1)
     107  #define fputs_quoted_lower(_d, _o)	fputs_quoted_case(_d, _o, -1)
     108  
     109  static inline void fputs_nonblank(const char *data, FILE *out)
     110  {
     111  	const char *p;
     112  
     113  	for (p = data; p && *p; p++) {
     114  		if (isblank((unsigned char) *p) ||
     115  		    (unsigned char) *p == 0x5c ||		/* \ */
     116  		    !isprint((unsigned char) *p) ||
     117  		    iscntrl((unsigned char) *p)) {
     118  
     119  			fprintf(out, "\\x%02x", (unsigned char) *p);
     120  
     121  		} else
     122  			fputc(*p, out);
     123  	}
     124  }
     125  
     126  #endif  /*  _CAREFULPUTC_H  */