1 /* $OpenBSD: nfs.c,v 1.9 2023/04/19 12:58:15 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Jasper Lievisse Adriaanse <jasper@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 */ 19 20 #include <sys/types.h> 21 #include <sys/mount.h> 22 #include <sys/signal.h> 23 #include <sys/sysctl.h> 24 #include <nfs/rpcv2.h> 25 #include <nfs/nfsproto.h> 26 #include <nfs/nfs.h> 27 28 #include <err.h> 29 #include <errno.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 #include "systat.h" 35 36 int check_nfs(void); 37 int select_client(void); 38 int select_server(void); 39 int read_nfs(void); 40 void print_client(void); 41 void print_server(void); 42 43 struct nfsstats nfsstats; 44 int num_client = 0; 45 int num_server = 0; 46 47 field_def fields_nfs[] = { 48 /* Client */ 49 {"RPC COUNTS", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 50 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 51 {"RPC INFO", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 52 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 53 {"CACHE INFO", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 54 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 55 56 /* Server */ 57 {"RPC COUNTS", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 58 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 59 {"CACHE STATS", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 60 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 61 {"WRITES", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 62 {"", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 63 }; 64 65 /* _V suffixed fields indicate a value column. */ 66 /* Client */ 67 #define FLD_NFS_C_RPC_COUNTS FIELD_ADDR(fields_nfs,0) 68 #define FLD_NFS_C_RPC_COUNTS_V FIELD_ADDR(fields_nfs,1) 69 #define FLD_NFS_C_RPC_INFO FIELD_ADDR(fields_nfs,2) 70 #define FLD_NFS_C_RPC_INFO_V FIELD_ADDR(fields_nfs,3) 71 #define FLD_NFS_C_CACHE_INFO FIELD_ADDR(fields_nfs,4) 72 #define FLD_NFS_C_CACHE_V FIELD_ADDR(fields_nfs,5) 73 74 /* Server */ 75 #define FLD_NFS_S_RPC_COUNTS FIELD_ADDR(fields_nfs,6) 76 #define FLD_NFS_S_RPC_COUNTS_V FIELD_ADDR(fields_nfs,7) 77 #define FLD_NFS_S_CACHE_STATS FIELD_ADDR(fields_nfs,8) 78 #define FLD_NFS_S_CACHE_STATS_V FIELD_ADDR(fields_nfs,9) 79 #define FLD_NFS_S_WRITES FIELD_ADDR(fields_nfs,10) 80 #define FLD_NFS_S_WRITES_V FIELD_ADDR(fields_nfs,11) 81 82 /* Define views */ 83 field_def *view_nfs_0[] = { 84 FLD_NFS_C_RPC_COUNTS, FLD_NFS_C_RPC_COUNTS_V, FLD_NFS_C_RPC_INFO, 85 FLD_NFS_C_RPC_INFO_V, FLD_NFS_C_CACHE_INFO, FLD_NFS_C_CACHE_V ,NULL 86 }; 87 88 field_def *view_nfs_1[] = { 89 FLD_NFS_S_RPC_COUNTS, FLD_NFS_S_RPC_COUNTS_V, FLD_NFS_S_CACHE_STATS, 90 FLD_NFS_S_CACHE_STATS_V, FLD_NFS_S_WRITES, FLD_NFS_S_WRITES_V, NULL 91 }; 92 93 /* Define view managers */ 94 struct view_manager nfs_client_mgr = { 95 "Client", select_client, read_nfs, NULL, print_header, 96 print_client, keyboard_callback, NULL, NULL 97 }; 98 99 struct view_manager nfs_server_mgr = { 100 "Server", select_server, read_nfs, NULL, print_header, 101 print_server, keyboard_callback, NULL, NULL 102 }; 103 104 field_view views_nfs[] = { 105 {view_nfs_0, "nfsclient", '8', &nfs_client_mgr}, 106 {view_nfs_1, "nfsserver", '9', &nfs_server_mgr}, 107 {NULL, NULL, 0, NULL} 108 }; 109 110 int 111 select_client(void) 112 { 113 num_disp = num_client; 114 return(0); 115 } 116 117 int 118 select_server(void) 119 { 120 num_disp = num_server; 121 return(0); 122 } 123 124 int 125 initnfs(void) 126 { 127 field_view *v; 128 129 for (v = views_nfs; v->name != NULL; v++) 130 add_view(v); 131 132 read_nfs(); 133 134 return(0); 135 } 136 137 /* 138 * We get all the information in one go and don't care about 139 * server or client fields (those will be '0' if not applicable). 140 */ 141 int 142 read_nfs(void) 143 { 144 struct nfsstats *p = &nfsstats; 145 int mib[3]; 146 size_t len = sizeof(*p); 147 148 mib[0] = CTL_VFS; 149 mib[1] = 2; /* NETDEV */ 150 mib[2] = NFS_NFSSTATS; 151 152 if (sysctl(mib, 3, p, &len, NULL, 0) == -1) 153 return(-1); 154 else 155 return(0); 156 } 157 158 159 /* 160 * As we want a view with multiple columns, mixed with labels and values, 161 * we can't use the regular dance and have to use our own (looong) dance 162 * to build the layout. 163 */ 164 void 165 print_client(void) 166 { 167 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Getattr"); 168 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 169 nfsstats.rpccnt[NFSPROC_GETATTR]); 170 print_fld_str(FLD_NFS_C_RPC_INFO, "TimedOut"); 171 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpctimeouts); 172 print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Hits "); 173 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_hits); 174 end_line(); 175 176 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Setattr"); 177 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 178 nfsstats.rpccnt[NFSPROC_SETATTR]); 179 print_fld_str(FLD_NFS_C_RPC_INFO, "Invalid"); 180 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcinvalid); 181 print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Misses"); 182 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_misses); 183 end_line(); 184 185 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Lookup"); 186 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 187 nfsstats.rpccnt[NFSPROC_LOOKUP]); 188 print_fld_str(FLD_NFS_C_RPC_INFO, "X Replies"); 189 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcunexpected); 190 print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Hits "); 191 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_hits); 192 end_line(); 193 194 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readlink"); 195 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 196 nfsstats.rpccnt[NFSPROC_READLINK]); 197 print_fld_str(FLD_NFS_C_RPC_INFO, "Retries"); 198 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcretries); 199 print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Misses "); 200 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_misses); 201 end_line(); 202 203 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Read"); 204 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 205 nfsstats.rpccnt[NFSPROC_READ]); 206 print_fld_str(FLD_NFS_C_RPC_INFO, "Requests"); 207 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcrequests); 208 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Hits "); 209 print_fld_ssize(FLD_NFS_C_CACHE_V, 210 nfsstats.biocache_reads-nfsstats.read_bios); 211 end_line(); 212 213 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Write"); 214 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_WRITE]); 215 print_fld_str(FLD_NFS_C_RPC_INFO, "FrcSync"); 216 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.forcedsync); 217 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Misses"); 218 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.read_bios); 219 end_line(); 220 221 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Create"); 222 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 223 nfsstats.rpccnt[NFSPROC_CREATE]); 224 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Hits "); 225 print_fld_ssize(FLD_NFS_C_CACHE_V, 226 nfsstats.biocache_writes-nfsstats.write_bios); 227 end_line(); 228 229 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Remove"); 230 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 231 nfsstats.rpccnt[NFSPROC_REMOVE]); 232 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Misses"); 233 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.write_bios); 234 end_line(); 235 236 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rename"); 237 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 238 nfsstats.rpccnt[NFSPROC_RENAME]); 239 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Hits "); 240 print_fld_ssize(FLD_NFS_C_CACHE_V, 241 nfsstats.biocache_readlinks-nfsstats.readlink_bios); 242 end_line(); 243 244 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Link"); 245 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_LINK]); 246 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Misses"); 247 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readlink_bios); 248 end_line(); 249 250 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Symlink"); 251 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 252 nfsstats.rpccnt[NFSPROC_SYMLINK]); 253 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Hits "); 254 print_fld_ssize(FLD_NFS_C_CACHE_V, 255 nfsstats.biocache_readdirs-nfsstats.readdir_bios); 256 end_line(); 257 258 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mkdir"); 259 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKDIR]); 260 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Misses"); 261 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readdir_bios); 262 end_line(); 263 264 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rmdir"); 265 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_RMDIR]); 266 print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Hits "); 267 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_hits); 268 end_line(); 269 270 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readdir"); 271 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 272 nfsstats.rpccnt[NFSPROC_READDIR]); 273 print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Misses"); 274 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_misses); 275 end_line(); 276 277 print_fld_str(FLD_NFS_C_RPC_COUNTS, "RdirPlus"); 278 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 279 nfsstats.rpccnt[NFSPROC_READDIRPLUS]); 280 end_line(); 281 282 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Access"); 283 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 284 nfsstats.rpccnt[NFSPROC_ACCESS]); 285 end_line(); 286 287 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mknod"); 288 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKNOD]); 289 end_line(); 290 291 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsstat"); 292 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 293 nfsstats.rpccnt[NFSPROC_FSSTAT]); 294 end_line(); 295 296 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsinfo"); 297 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 298 nfsstats.rpccnt[NFSPROC_FSINFO]); 299 end_line(); 300 301 print_fld_str(FLD_NFS_C_RPC_COUNTS, "PathConf"); 302 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 303 nfsstats.rpccnt[NFSPROC_PATHCONF]); 304 end_line(); 305 306 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Commit"); 307 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 308 nfsstats.rpccnt[NFSPROC_COMMIT]); 309 end_line(); 310 } 311 312 void 313 print_server(void) 314 { 315 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Getattr"); 316 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 317 nfsstats.srvrpccnt[NFSPROC_GETATTR]); 318 print_fld_str(FLD_NFS_S_CACHE_STATS, "Inprog"); 319 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_inproghits); 320 print_fld_str(FLD_NFS_S_WRITES, "WriteOps"); 321 print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvvop_writes); 322 end_line(); 323 324 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Setattr"); 325 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 326 nfsstats.srvrpccnt[NFSPROC_SETATTR]); 327 print_fld_str(FLD_NFS_S_CACHE_STATS, "Idem"); 328 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, 329 nfsstats.srvcache_idemdonehits); 330 print_fld_str(FLD_NFS_S_WRITES, "WriteRPC"); 331 print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvrpccnt[NFSPROC_WRITE]); 332 end_line(); 333 334 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Lookup"); 335 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 336 nfsstats.srvrpccnt[NFSPROC_LOOKUP]); 337 print_fld_str(FLD_NFS_S_CACHE_STATS, "Non-idem"); 338 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, 339 nfsstats.srvcache_nonidemdonehits); 340 print_fld_str(FLD_NFS_S_WRITES, "Opsaved"); 341 print_fld_ssize(FLD_NFS_S_WRITES_V, 342 nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes); 343 end_line(); 344 345 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readlink"); 346 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 347 nfsstats.srvrpccnt[NFSPROC_READLINK]); 348 print_fld_str(FLD_NFS_S_CACHE_STATS, "Misses"); 349 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_misses); 350 end_line(); 351 352 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Read"); 353 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 354 nfsstats.srvrpccnt[NFSPROC_READ]); 355 end_line(); 356 357 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Write"); 358 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 359 nfsstats.srvrpccnt[NFSPROC_WRITE]); 360 end_line(); 361 362 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Create"); 363 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 364 nfsstats.srvrpccnt[NFSPROC_CREATE]); 365 end_line(); 366 367 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Remove"); 368 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 369 nfsstats.srvrpccnt[NFSPROC_REMOVE]); 370 end_line(); 371 372 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rename"); 373 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 374 nfsstats.srvrpccnt[NFSPROC_RENAME]); 375 end_line(); 376 377 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Link"); 378 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 379 nfsstats.srvrpccnt[NFSPROC_LINK]); 380 end_line(); 381 382 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Symlink"); 383 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 384 nfsstats.srvrpccnt[NFSPROC_SYMLINK]); 385 end_line(); 386 387 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mkdir"); 388 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 389 nfsstats.srvrpccnt[NFSPROC_MKDIR]); 390 end_line(); 391 392 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rmdir"); 393 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 394 nfsstats.srvrpccnt[NFSPROC_RMDIR]); 395 end_line(); 396 397 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readdir"); 398 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 399 nfsstats.srvrpccnt[NFSPROC_READDIR]); 400 end_line(); 401 402 print_fld_str(FLD_NFS_S_RPC_COUNTS, "RdirPlus"); 403 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 404 nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]); 405 end_line(); 406 407 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Access"); 408 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 409 nfsstats.srvrpccnt[NFSPROC_ACCESS]); 410 end_line(); 411 412 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mknod"); 413 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 414 nfsstats.srvrpccnt[NFSPROC_MKNOD]); 415 end_line(); 416 417 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsstat"); 418 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 419 nfsstats.srvrpccnt[NFSPROC_FSSTAT]); 420 end_line(); 421 422 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsinfo"); 423 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 424 nfsstats.srvrpccnt[NFSPROC_FSINFO]); 425 end_line(); 426 427 print_fld_str(FLD_NFS_S_RPC_COUNTS, "PathConf"); 428 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 429 nfsstats.srvrpccnt[NFSPROC_PATHCONF]); 430 end_line(); 431 432 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Commit"); 433 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 434 nfsstats.srvrpccnt[NFSPROC_COMMIT]); 435 end_line(); 436 437 /* This creates an empty space on screen to separate the two blocks */ 438 print_fld_str(FLD_NFS_S_RPC_COUNTS, ""); 439 end_line(); 440 441 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Ret-Failed"); 442 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpc_errs); 443 print_fld_str(FLD_NFS_S_CACHE_STATS, "Faults"); 444 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srv_errs); 445 end_line(); 446 } 447