/* * Delete Printer helper for Samba and CUPS * * Compile with gcc -Wall deleteprinter.c -o deleteprinter and set as your * deleteprinter command in smb.conf. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #define CONFFILE "/etc/samba/smb.conf" int main( int argc, char *argv[] ) { pid_t pid = 0; FILE *smbconf = NULL; FILE *newconf = NULL; char *printer; char *sharename; int found = 0; /* Syslog support */ openlog( "deleteprinter", LOG_PID, LOG_LPR ); /* Args are: - printer /share/ name */ if ( argc != 2 ) { syslog( LOG_ERR, "Expected 1 argument, found %d", argc - 1 ); exit( 1 ); } else { syslog( LOG_INFO, "deleteprinter '%s'", argv[1] ); } sharename = strdup( argv[1] ); /* Try and find the printer in smb.conf. We need this for two * reasons: firstly, to delete any per-share info this printer holds, * and secondly to get the actual printer name. */ if (( newconf = fopen( CONFFILE ".new", "w" )) == NULL ) { syslog( LOG_ERR, "Can't create %s.new (%m)", CONFFILE ); exit( 1 ); } if (( smbconf = fopen( CONFFILE, "r" )) != NULL ) { char *line = NULL; size_t linelen, dummy; while(( linelen = getline( &line, &dummy, smbconf )) != -1 ) { /* skip comments and blanks */ size_t looking_at = strspn( line, " \t\r\n" ); if ( linelen == looking_at || line[ looking_at ] == '#' || line[ looking_at ] == ';' ) { fprintf( newconf, "%s", line ); continue; } if ( line[looking_at] == '[' ) { if ( !found && !strncmp( &line[looking_at + 1], sharename, strlen( sharename ))) { syslog( LOG_INFO, "found an entry for %s in %s", sharename, CONFFILE ); found = 1; continue; } else if ( found ) { /* end of definition */ found = 0; } else { /* ignore this share */ } } if ( !found ) { fprintf( newconf, "%s", line ); /* XXX */ } if ( found && !strncmp( &line[looking_at], "printer name", strlen( "printer name" ))) { looking_at += strlen( "printer name" ); looking_at += strspn( &line[looking_at], " \t="); printer = strdup( &line[looking_at] ); if ( strlen( printer )) { /* trailing newline */ printer[ strlen( printer ) - 1 ] = '\0'; } if ( strlen( printer )) { /* */ } else { syslog( LOG_ERR, "printer name for %s not specified!", sharename ); exit( 1 ); } } } fclose( smbconf ); fclose( newconf ); } else { syslog( LOG_ERR, "failed to open %s: %m", CONFFILE ); exit( 1 ); } /* default printer name */ if ( printer == NULL ) { printer = strdup( sharename ); } syslog( LOG_INFO, "deleting printer %s", printer ); pid = fork(); if ( pid == -1 ) { syslog( LOG_ERR, "error forking: %m" ); exit( 1 ); } if ( !pid ) { /* Child */ execl( "/usr/sbin/lpadmin", "lpadmin", "-x", printer, NULL ); syslog( LOG_ERR, "exec error running lpadmin: %m" ); exit( 1 ); } else { int status; waitpid( pid, &status, 0 ); /* Bail on error */ if ( status != 0 ) { syslog( LOG_ERR, "lpadmin exited with status %d", status ); exit( 1 ); } } /* Finally, fix smb.conf */ rename( CONFFILE, CONFFILE ".old" ); rename( CONFFILE ".new", CONFFILE ); /* unnecessary, but tidy */ free( sharename ); free( printer ); return 0; }