1 /* seeker.c; part of GNU CSSC.
2  *
3  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
4  * 2008, 2009, 2010, 2001, 2014, 2019 Free Software Foundation, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Program that determines if the target system can seek on its standard
20  * input.
21  */
22 #include <config.h>
23 
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 
30 #include <unistd.h>
31 #include <sys/types.h>
32 
33 
34 
35 #define ERR_USAGE (1)
36 
37 void usage(const char *name, int retval);
38 
39 #ifdef HAVE_FSETPOS
40 static void
try_getpos(FILE * f)41 try_getpos(FILE *f)
42 {
43   fpos_t pos;
44   int rv;
45 
46   rv = fgetpos(f, &pos);
47   printf("fgetpos() returns %d\n", rv);
48   rv = fsetpos(f, &pos);
49   printf("fsetpos() returns %d\n", rv);
50 }
51 #endif
52 
53 static void
try_fseek(FILE * f)54 try_fseek(FILE *f)
55 {
56   long lrv;
57   int rv;
58 
59   lrv = ftell(f);
60   printf("ftell() returns %ld\n", lrv);
61   rv = fseek(f, SEEK_SET, lrv);
62   printf("fseek() returns %d\n", rv);
63 }
64 
65 static void
try_lseek()66 try_lseek()
67 {
68   off_t pos;
69   pos = lseek(0, 0, SEEK_CUR);
70   printf("lseek() returns %ld [SEEK_CUR]\n", (long)pos);
71   pos = lseek(0, pos, SEEK_CUR);
72   printf("lseek() returns %ld [SEEK_SET]\n", (long)pos);
73 }
74 
75 
do_help(const char * name)76 int do_help(const char *name)
77 {
78   usage(name, 0);
79   return 0;
80 }
81 
do_unbuffered(const char * name)82 int do_unbuffered(const char *name)
83 {
84   (void) name;
85   printf("stdin is unbuffered\n");
86   setvbuf(stdin, (char*)NULL, _IONBF, 0u);
87   return 0;
88 }
89 
do_blockbuffered(const char * name)90 int do_blockbuffered(const char *name)
91 {
92   (void) name;
93   printf("stdin is fully-buffered\n");
94   setvbuf(stdin, (char*)NULL, _IOFBF, BUFSIZ);
95   return 0;
96 }
97 
do_linebuffered(const char * name)98 int do_linebuffered(const char *name)
99 {
100   (void) name;
101   printf("stdin is line-buffered\n");
102   setvbuf(stdin, (char *)NULL, _IOLBF, 0);
103   return 0;
104 }
105 
do_nothing(const char * name)106 int do_nothing(const char *name)
107 {
108   (void) name;
109   printf("stdin is buffered in the default way\n");
110   return 0;
111 }
112 
113 
114 struct optact
115 {
116   const char *option;
117   int (*action)(const char*);
118 };
119 struct optact actions[]=
120 {
121   { "--help", do_help },
122   { "--unbuffered", do_unbuffered },
123   { "--fully-buffered", do_blockbuffered },
124   { "--line-buffered", do_linebuffered },
125   { "--default-buffering", do_nothing }
126 };
127 #define NOPTIONS (sizeof(actions)/sizeof(actions[0]))
128 
129 
130 
usage(const char * name,int retval)131 void usage(const char *name, int retval)
132 {
133   unsigned int j;
134 
135   fprintf(stderr, "usage: %s ", name);
136   for (j=0u; j<NOPTIONS; ++j)
137     fprintf(stderr, "[%s] ", actions[j].option);
138   fprintf(stderr, "\n");
139   exit(retval);
140 }
141 
main(int argc,char * argv[])142 int main(int argc, char *argv[])
143 {
144   int i;
145   unsigned int j;
146 
147 
148   for (i=1; i<argc; ++i)
149     {
150       if ('-' == argv[i][0])
151         {
152           for (j=0u; j<NOPTIONS; ++j)
153             {
154               if (0 == strcmp(argv[i], actions[j].option))
155                 {
156                   (*actions[j].action)(argv[0]);
157                   break;
158                 }
159             }
160 
161           if (NOPTIONS == j)
162             {
163               fprintf(stderr, "Unknown option `%s'\n", argv[i]);
164               usage(argv[0], ERR_USAGE);        /* unknown option */
165             }
166         }
167       else                      /* not an option */
168         {
169           usage(argv[0], ERR_USAGE);
170         }
171     }
172 #ifdef HAVE_FSETPOS
173   try_getpos(stdin);
174 #else
175   printf("fgetpos() not supported.\n");
176 #endif
177   try_fseek(stdin);
178   try_lseek();
179   return 0;
180 }
181